@keenthemes/ktui 1.2.4 → 1.2.5
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/dist/ktui.js +590 -131
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +76 -40
- package/lib/cjs/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-checkbox.js +34 -15
- package/lib/cjs/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-contracts.d.ts +3 -3
- package/lib/cjs/components/datatable/datatable-contracts.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-local-provider.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-local-provider.js +13 -7
- package/lib/cjs/components/datatable/datatable-local-provider.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-pagination-renderer.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js +31 -15
- package/lib/cjs/components/datatable/datatable-pagination-renderer.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-remote-provider.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-remote-provider.js +3 -0
- package/lib/cjs/components/datatable/datatable-remote-provider.js.map +1 -1
- package/lib/cjs/components/datatable/datatable-table-renderer.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable-table-renderer.js +14 -6
- package/lib/cjs/components/datatable/datatable-table-renderer.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.d.ts.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +120 -54
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.d.ts +2 -2
- package/lib/cjs/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/cjs/components/dropdown/dropdown.js +68 -31
- package/lib/cjs/components/dropdown/dropdown.js.map +1 -1
- package/lib/cjs/components/input-number/index.d.ts +7 -0
- package/lib/cjs/components/input-number/index.d.ts.map +1 -0
- package/lib/cjs/components/input-number/index.js +10 -0
- package/lib/cjs/components/input-number/index.js.map +1 -0
- package/lib/cjs/components/input-number/input-number.d.ts +40 -0
- package/lib/cjs/components/input-number/input-number.d.ts.map +1 -0
- package/lib/cjs/components/input-number/input-number.js +248 -0
- package/lib/cjs/components/input-number/input-number.js.map +1 -0
- package/lib/cjs/components/input-number/types.d.ts +30 -0
- package/lib/cjs/components/input-number/types.d.ts.map +1 -0
- package/lib/cjs/components/input-number/types.js +7 -0
- package/lib/cjs/components/input-number/types.js.map +1 -0
- package/lib/cjs/components/select/config.d.ts +1 -0
- package/lib/cjs/components/select/config.d.ts.map +1 -1
- package/lib/cjs/components/select/config.js +2 -1
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/select.d.ts +8 -1
- package/lib/cjs/components/select/select.d.ts.map +1 -1
- package/lib/cjs/components/select/select.js +14 -1
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.d.ts.map +1 -1
- package/lib/cjs/components/select/tags.js +10 -0
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/cjs/index.d.ts +4 -0
- package/lib/cjs/index.d.ts.map +1 -1
- package/lib/cjs/index.js +5 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-checkbox.js +34 -15
- package/lib/esm/components/datatable/datatable-checkbox.js.map +1 -1
- package/lib/esm/components/datatable/datatable-contracts.d.ts +3 -3
- package/lib/esm/components/datatable/datatable-contracts.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-local-provider.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-local-provider.js +13 -7
- package/lib/esm/components/datatable/datatable-local-provider.js.map +1 -1
- package/lib/esm/components/datatable/datatable-pagination-renderer.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-pagination-renderer.js +31 -15
- package/lib/esm/components/datatable/datatable-pagination-renderer.js.map +1 -1
- package/lib/esm/components/datatable/datatable-remote-provider.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-remote-provider.js +3 -0
- package/lib/esm/components/datatable/datatable-remote-provider.js.map +1 -1
- package/lib/esm/components/datatable/datatable-table-renderer.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable-table-renderer.js +14 -6
- package/lib/esm/components/datatable/datatable-table-renderer.js.map +1 -1
- package/lib/esm/components/datatable/datatable.d.ts.map +1 -1
- package/lib/esm/components/datatable/datatable.js +120 -54
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/dropdown/dropdown.d.ts +2 -2
- package/lib/esm/components/dropdown/dropdown.d.ts.map +1 -1
- package/lib/esm/components/dropdown/dropdown.js +68 -31
- package/lib/esm/components/dropdown/dropdown.js.map +1 -1
- package/lib/esm/components/input-number/index.d.ts +7 -0
- package/lib/esm/components/input-number/index.d.ts.map +1 -0
- package/lib/esm/components/input-number/index.js +6 -0
- package/lib/esm/components/input-number/index.js.map +1 -0
- package/lib/esm/components/input-number/input-number.d.ts +40 -0
- package/lib/esm/components/input-number/input-number.d.ts.map +1 -0
- package/lib/esm/components/input-number/input-number.js +245 -0
- package/lib/esm/components/input-number/input-number.js.map +1 -0
- package/lib/esm/components/input-number/types.d.ts +30 -0
- package/lib/esm/components/input-number/types.d.ts.map +1 -0
- package/lib/esm/components/input-number/types.js +6 -0
- package/lib/esm/components/input-number/types.js.map +1 -0
- package/lib/esm/components/select/config.d.ts +1 -0
- package/lib/esm/components/select/config.d.ts.map +1 -1
- package/lib/esm/components/select/config.js +2 -1
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/select.d.ts +8 -1
- package/lib/esm/components/select/select.d.ts.map +1 -1
- package/lib/esm/components/select/select.js +14 -1
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.d.ts.map +1 -1
- package/lib/esm/components/select/tags.js +11 -1
- package/lib/esm/components/select/tags.js.map +1 -1
- package/lib/esm/index.d.ts +4 -0
- package/lib/esm/index.d.ts.map +1 -1
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +5 -11
- package/src/components/datatable/datatable-checkbox.ts +34 -23
- package/src/components/datatable/datatable-contracts.ts +3 -3
- package/src/components/datatable/datatable-local-provider.ts +12 -13
- package/src/components/datatable/datatable-pagination-renderer.ts +34 -20
- package/src/components/datatable/datatable-remote-provider.ts +3 -0
- package/src/components/datatable/datatable-table-renderer.ts +40 -32
- package/src/components/datatable/datatable.ts +122 -79
- package/src/components/dropdown/dropdown.ts +86 -58
- package/src/components/input/input-group.css +14 -1
- package/src/components/input-number/__tests__/input-number.test.ts +278 -0
- package/src/components/input-number/index.ts +11 -0
- package/src/components/input-number/input-number.ts +267 -0
- package/src/components/input-number/types.ts +32 -0
- package/src/components/select/__tests__/ux-behaviors.test.ts +72 -0
- package/src/components/select/config.ts +3 -1
- package/src/components/select/select.css +23 -20
- package/src/components/select/select.ts +15 -1
- package/src/components/select/tags.ts +14 -1
- package/src/index.ts +9 -0
|
@@ -13,6 +13,7 @@ import KTDom from '../../helpers/dom';
|
|
|
13
13
|
import KTData from '../../helpers/data';
|
|
14
14
|
import KTEventHandler from '../../helpers/event-handler';
|
|
15
15
|
import KTComponent from '../component';
|
|
16
|
+
import { KTCallableType } from '../../types';
|
|
16
17
|
import { KTDropdownConfigInterface, KTDropdownInterface } from './types';
|
|
17
18
|
|
|
18
19
|
declare global {
|
|
@@ -41,8 +42,8 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
41
42
|
};
|
|
42
43
|
protected override _config: KTDropdownConfigInterface = this._defaultConfig;
|
|
43
44
|
protected _disabled: boolean = false;
|
|
44
|
-
protected _toggleElement
|
|
45
|
-
protected _menuElement
|
|
45
|
+
protected _toggleElement!: HTMLElement;
|
|
46
|
+
protected _menuElement!: HTMLElement;
|
|
46
47
|
protected _isTransitioning: boolean = false;
|
|
47
48
|
protected _isOpen: boolean = false;
|
|
48
49
|
/** Timestamp when _show() was last called; used to ignore duplicate _hide() from double handlers */
|
|
@@ -56,20 +57,25 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
this._init(element);
|
|
60
|
+
if (!this._element) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
59
63
|
this._buildConfig(config);
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
const toggle = this._element.querySelector<HTMLElement>(
|
|
62
66
|
'[data-kt-dropdown-toggle]',
|
|
63
|
-
)
|
|
64
|
-
if (!
|
|
67
|
+
);
|
|
68
|
+
if (!toggle) {
|
|
65
69
|
return;
|
|
66
70
|
}
|
|
67
|
-
|
|
71
|
+
const menu = this._element.querySelector<HTMLElement>(
|
|
68
72
|
'[data-kt-dropdown-menu]',
|
|
69
|
-
)
|
|
70
|
-
if (!
|
|
73
|
+
);
|
|
74
|
+
if (!menu) {
|
|
71
75
|
return;
|
|
72
76
|
}
|
|
77
|
+
this._toggleElement = toggle;
|
|
78
|
+
this._menuElement = menu;
|
|
73
79
|
|
|
74
80
|
KTData.set(this._menuElement, 'dropdownElement', this._element);
|
|
75
81
|
this._setupNestedDropdowns();
|
|
@@ -125,10 +131,13 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
125
131
|
|
|
126
132
|
if (this._getOption('trigger') !== 'hover') return;
|
|
127
133
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
const root = this._element;
|
|
135
|
+
if (!root) return;
|
|
136
|
+
|
|
137
|
+
if (KTData.get(root, 'hover') === '1') {
|
|
138
|
+
clearTimeout(KTData.get(root, 'timeout') as number);
|
|
139
|
+
KTData.remove(root, 'hover');
|
|
140
|
+
KTData.remove(root, 'timeout');
|
|
132
141
|
}
|
|
133
142
|
|
|
134
143
|
this._show();
|
|
@@ -139,22 +148,26 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
139
148
|
|
|
140
149
|
if (this._getOption('trigger') !== 'hover') return;
|
|
141
150
|
|
|
142
|
-
const
|
|
143
|
-
|
|
151
|
+
const root = this._element;
|
|
152
|
+
if (!root) return;
|
|
153
|
+
|
|
154
|
+
const relatedTarget = event.relatedTarget as HTMLElement | null;
|
|
155
|
+
const isWithinDropdown =
|
|
156
|
+
relatedTarget !== null && root.contains(relatedTarget);
|
|
144
157
|
|
|
145
158
|
if (isWithinDropdown) return;
|
|
146
159
|
|
|
147
160
|
const timeout = setTimeout(
|
|
148
161
|
() => {
|
|
149
|
-
if (KTData.get(
|
|
162
|
+
if (KTData.get(root, 'hover') === '1') {
|
|
150
163
|
this._hide();
|
|
151
164
|
}
|
|
152
165
|
},
|
|
153
166
|
parseInt(this._getOption('hoverTimeout') as string),
|
|
154
167
|
);
|
|
155
168
|
|
|
156
|
-
KTData.set(
|
|
157
|
-
KTData.set(
|
|
169
|
+
KTData.set(root, 'hover', '1');
|
|
170
|
+
KTData.set(root, 'timeout', timeout);
|
|
158
171
|
}
|
|
159
172
|
|
|
160
173
|
protected _toggle(): void {
|
|
@@ -175,10 +188,13 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
175
188
|
this._dispatchEvent('show', payload);
|
|
176
189
|
if (payload.cancel) return;
|
|
177
190
|
|
|
178
|
-
|
|
191
|
+
const root = this._element;
|
|
192
|
+
if (!root) return;
|
|
193
|
+
|
|
194
|
+
KTDropdown.hide(root);
|
|
179
195
|
|
|
180
196
|
let zIndex: number = parseInt(this._getOption('zindex') as string);
|
|
181
|
-
const parentZindex: number = KTDom.getHighestZindex(
|
|
197
|
+
const parentZindex: number = KTDom.getHighestZindex(root);
|
|
182
198
|
|
|
183
199
|
if (parentZindex !== null && parentZindex >= zIndex) {
|
|
184
200
|
zIndex = parentZindex + 1;
|
|
@@ -197,7 +213,7 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
197
213
|
);
|
|
198
214
|
this._toggleElement.classList.add('active');
|
|
199
215
|
this._menuElement.classList.add('open');
|
|
200
|
-
|
|
216
|
+
root.classList.add('open');
|
|
201
217
|
|
|
202
218
|
this._initPopper();
|
|
203
219
|
|
|
@@ -221,12 +237,15 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
221
237
|
this._dispatchEvent('hide', payload);
|
|
222
238
|
if (payload.cancel) return;
|
|
223
239
|
|
|
240
|
+
const root = this._element;
|
|
241
|
+
if (!root) return;
|
|
242
|
+
|
|
224
243
|
this._menuElement.style.opacity = '1';
|
|
225
244
|
KTDom.reflow(this._menuElement);
|
|
226
245
|
this._menuElement.style.opacity = '0';
|
|
227
246
|
this._menuElement.classList.remove('open');
|
|
228
247
|
this._toggleElement.classList.remove('active');
|
|
229
|
-
|
|
248
|
+
root.classList.remove('open');
|
|
230
249
|
|
|
231
250
|
KTDom.transitionEnd(this._menuElement, () => {
|
|
232
251
|
this._isTransitioning = false;
|
|
@@ -262,20 +281,27 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
262
281
|
this._menuElement,
|
|
263
282
|
this._getPopperConfig(),
|
|
264
283
|
);
|
|
265
|
-
|
|
284
|
+
const root = this._element;
|
|
285
|
+
if (root) {
|
|
286
|
+
KTData.set(root, 'popper', popper);
|
|
287
|
+
}
|
|
266
288
|
}
|
|
267
289
|
}
|
|
268
290
|
|
|
269
291
|
protected _destroyPopper(): void {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
292
|
+
const root = this._element;
|
|
293
|
+
if (!root) return;
|
|
294
|
+
if (KTData.has(root, 'popper')) {
|
|
295
|
+
(KTData.get(root, 'popper') as PopperInstance).destroy();
|
|
296
|
+
KTData.remove(root, 'popper');
|
|
273
297
|
}
|
|
274
298
|
}
|
|
275
299
|
|
|
276
300
|
protected _isDropdownOpen(): boolean {
|
|
301
|
+
const root = this._element;
|
|
302
|
+
if (!root) return false;
|
|
277
303
|
return (
|
|
278
|
-
|
|
304
|
+
root.classList.contains('open') &&
|
|
279
305
|
this._menuElement.classList.contains('open')
|
|
280
306
|
);
|
|
281
307
|
}
|
|
@@ -379,7 +405,7 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
379
405
|
}
|
|
380
406
|
|
|
381
407
|
// Static Methods
|
|
382
|
-
public static getElement(reference: HTMLElement): HTMLElement {
|
|
408
|
+
public static getElement(reference: HTMLElement): HTMLElement | null {
|
|
383
409
|
if (reference && reference.hasAttribute('data-kt-dropdown-initialized'))
|
|
384
410
|
return reference;
|
|
385
411
|
|
|
@@ -407,12 +433,13 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
407
433
|
return null;
|
|
408
434
|
}
|
|
409
435
|
|
|
410
|
-
public static getInstance(element: HTMLElement): KTDropdown {
|
|
411
|
-
|
|
436
|
+
public static getInstance(element: HTMLElement): KTDropdown | null {
|
|
437
|
+
const resolved = this.getElement(element);
|
|
412
438
|
|
|
413
|
-
if (!
|
|
439
|
+
if (!resolved) {
|
|
414
440
|
return null;
|
|
415
441
|
}
|
|
442
|
+
element = resolved;
|
|
416
443
|
|
|
417
444
|
if (KTData.has(element, 'dropdown')) {
|
|
418
445
|
const instance = KTData.get(element, 'dropdown') as KTDropdown;
|
|
@@ -490,8 +517,9 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
490
517
|
document.addEventListener('keydown', (event: KeyboardEvent) => {
|
|
491
518
|
const dropdownEl = document.querySelector(
|
|
492
519
|
'.open[data-kt-dropdown-initialized]',
|
|
493
|
-
);
|
|
494
|
-
|
|
520
|
+
) as HTMLElement | null;
|
|
521
|
+
if (!dropdownEl) return;
|
|
522
|
+
const dropdown = KTDropdown.getInstance(dropdownEl);
|
|
495
523
|
if (!dropdown || !dropdown._getOption('keyboard')) return;
|
|
496
524
|
|
|
497
525
|
if (
|
|
@@ -508,12 +536,13 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
508
536
|
document.body,
|
|
509
537
|
'[data-kt-dropdown-toggle], [data-kt-dropdown-menu]',
|
|
510
538
|
'mouseover',
|
|
511
|
-
(event
|
|
539
|
+
((event?: Event, target?: HTMLElement) => {
|
|
540
|
+
if (!event || !target) return;
|
|
512
541
|
const dropdown = KTDropdown.getInstance(target);
|
|
513
542
|
if (dropdown && dropdown._getOption('trigger') === 'hover') {
|
|
514
543
|
dropdown.mouseover(event as MouseEvent);
|
|
515
544
|
}
|
|
516
|
-
},
|
|
545
|
+
}) as KTCallableType,
|
|
517
546
|
);
|
|
518
547
|
}
|
|
519
548
|
|
|
@@ -522,41 +551,40 @@ export class KTDropdown extends KTComponent implements KTDropdownInterface {
|
|
|
522
551
|
document.body,
|
|
523
552
|
'[data-kt-dropdown-toggle], [data-kt-dropdown-menu]',
|
|
524
553
|
'mouseout',
|
|
525
|
-
(event
|
|
554
|
+
((event?: Event, target?: HTMLElement) => {
|
|
555
|
+
if (!event || !target) return;
|
|
526
556
|
const dropdown = KTDropdown.getInstance(target);
|
|
527
557
|
if (dropdown && dropdown._getOption('trigger') === 'hover') {
|
|
528
558
|
dropdown.mouseout(event as MouseEvent);
|
|
529
559
|
}
|
|
530
|
-
},
|
|
560
|
+
}) as KTCallableType,
|
|
531
561
|
);
|
|
532
562
|
}
|
|
533
563
|
|
|
534
564
|
public static handleClick(): void {
|
|
535
|
-
KTEventHandler.on(
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
(event
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
);
|
|
565
|
+
KTEventHandler.on(document.body, '[data-kt-dropdown-toggle]', 'click', ((
|
|
566
|
+
event?: Event,
|
|
567
|
+
target?: HTMLElement,
|
|
568
|
+
) => {
|
|
569
|
+
if (!event || !target) return;
|
|
570
|
+
const dropdown = KTDropdown.getInstance(target);
|
|
571
|
+
if (dropdown) {
|
|
572
|
+
dropdown.click(event);
|
|
573
|
+
}
|
|
574
|
+
}) as KTCallableType);
|
|
546
575
|
}
|
|
547
576
|
|
|
548
577
|
public static handleDismiss(): void {
|
|
549
|
-
KTEventHandler.on(
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
(event
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
);
|
|
578
|
+
KTEventHandler.on(document.body, '[data-kt-dropdown-dismiss]', 'click', ((
|
|
579
|
+
event?: Event,
|
|
580
|
+
target?: HTMLElement,
|
|
581
|
+
) => {
|
|
582
|
+
if (!event || !target) return;
|
|
583
|
+
const dropdown = KTDropdown.getInstance(target);
|
|
584
|
+
if (dropdown) {
|
|
585
|
+
dropdown.hide();
|
|
586
|
+
}
|
|
587
|
+
}) as KTCallableType);
|
|
560
588
|
}
|
|
561
589
|
|
|
562
590
|
public static initHandlers(): void {
|
|
@@ -30,8 +30,21 @@
|
|
|
30
30
|
@apply rounded-e-none!;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/* Leading button before field: square inline-end + drop shadow so join matches addon pattern */
|
|
34
|
+
.kt-btn:has(+ input.kt-input),
|
|
35
|
+
.kt-btn:has(+ textarea.kt-input),
|
|
36
|
+
.kt-btn:has(+ .kt-input) {
|
|
37
|
+
@apply rounded-e-none! shadow-none!;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.kt-btn:has(+ input.kt-input).kt-btn-outline,
|
|
41
|
+
.kt-btn:has(+ textarea.kt-input).kt-btn-outline,
|
|
42
|
+
.kt-btn:has(+ .kt-input).kt-btn-outline {
|
|
43
|
+
@apply border-e-0!;
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
.kt-input + .kt-btn {
|
|
34
|
-
@apply rounded-s-none!;
|
|
47
|
+
@apply rounded-s-none! shadow-none!;
|
|
35
48
|
}
|
|
36
49
|
|
|
37
50
|
.kt-input + .kt-btn.kt-btn-outline {
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for KTInputNumber component
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
6
|
+
import { KTInputNumber } from '../input-number';
|
|
7
|
+
|
|
8
|
+
describe('KTInputNumber', () => {
|
|
9
|
+
let container: HTMLElement;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
document.body.innerHTML = '';
|
|
13
|
+
container = document.createElement('div');
|
|
14
|
+
container.id = 'test-container';
|
|
15
|
+
document.body.appendChild(container);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
document.body.innerHTML = '';
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
describe('initialization', () => {
|
|
23
|
+
it('initializes on wrapper with nested number input', () => {
|
|
24
|
+
const wrap = document.createElement('div');
|
|
25
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
26
|
+
const input = document.createElement('input');
|
|
27
|
+
input.type = 'number';
|
|
28
|
+
input.min = '0';
|
|
29
|
+
input.max = '10';
|
|
30
|
+
input.value = '3';
|
|
31
|
+
wrap.appendChild(input);
|
|
32
|
+
container.appendChild(wrap);
|
|
33
|
+
|
|
34
|
+
const instance = new KTInputNumber(wrap);
|
|
35
|
+
expect(instance.getElement()).toBe(wrap);
|
|
36
|
+
expect(instance.getNumberInput()).toBe(input);
|
|
37
|
+
expect(instance.getValue()).toBe(3);
|
|
38
|
+
instance.dispose();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('initializes on the number input root', () => {
|
|
42
|
+
const input = document.createElement('input');
|
|
43
|
+
input.type = 'number';
|
|
44
|
+
input.setAttribute('data-kt-input-number', 'true');
|
|
45
|
+
input.min = '0';
|
|
46
|
+
input.max = '5';
|
|
47
|
+
input.value = '2';
|
|
48
|
+
container.appendChild(input);
|
|
49
|
+
|
|
50
|
+
const instance = new KTInputNumber(input);
|
|
51
|
+
expect(instance.getElement()).toBe(input);
|
|
52
|
+
expect(instance.getNumberInput()).toBe(input);
|
|
53
|
+
instance.dispose();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('binds to the first number input when multiple exist', () => {
|
|
57
|
+
const wrap = document.createElement('div');
|
|
58
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
59
|
+
const a = document.createElement('input');
|
|
60
|
+
a.type = 'number';
|
|
61
|
+
a.value = '1';
|
|
62
|
+
const b = document.createElement('input');
|
|
63
|
+
b.type = 'number';
|
|
64
|
+
b.value = '2';
|
|
65
|
+
wrap.appendChild(a);
|
|
66
|
+
wrap.appendChild(b);
|
|
67
|
+
container.appendChild(wrap);
|
|
68
|
+
|
|
69
|
+
const instance = new KTInputNumber(wrap);
|
|
70
|
+
expect(instance.getNumberInput()).toBe(a);
|
|
71
|
+
instance.dispose();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('does not initialize without a number input', () => {
|
|
75
|
+
const wrap = document.createElement('div');
|
|
76
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
77
|
+
container.appendChild(wrap);
|
|
78
|
+
const instance = new KTInputNumber(wrap);
|
|
79
|
+
expect(instance.getElement()).toBeNull();
|
|
80
|
+
expect(instance.getNumberInput()).toBeNull();
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('events', () => {
|
|
85
|
+
it('dispatches kt.input-number.input with payload on native input', () => {
|
|
86
|
+
const wrap = document.createElement('div');
|
|
87
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
88
|
+
const input = document.createElement('input');
|
|
89
|
+
input.type = 'number';
|
|
90
|
+
input.min = '0';
|
|
91
|
+
input.max = '100';
|
|
92
|
+
input.step = '2';
|
|
93
|
+
input.value = '4';
|
|
94
|
+
wrap.appendChild(input);
|
|
95
|
+
container.appendChild(wrap);
|
|
96
|
+
|
|
97
|
+
const instance = new KTInputNumber(wrap);
|
|
98
|
+
const spy = vi.fn();
|
|
99
|
+
wrap.addEventListener('kt.input-number.input', spy);
|
|
100
|
+
|
|
101
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
102
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
103
|
+
expect(spy.mock.calls[0][0].detail.payload).toMatchObject({
|
|
104
|
+
value: 4,
|
|
105
|
+
valueAsString: '4',
|
|
106
|
+
min: 0,
|
|
107
|
+
max: 100,
|
|
108
|
+
step: 2,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
instance.dispose();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('dispatches kt.input-number.change on native change', () => {
|
|
115
|
+
const wrap = document.createElement('div');
|
|
116
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
117
|
+
const input = document.createElement('input');
|
|
118
|
+
input.type = 'number';
|
|
119
|
+
input.value = '7';
|
|
120
|
+
wrap.appendChild(input);
|
|
121
|
+
container.appendChild(wrap);
|
|
122
|
+
|
|
123
|
+
const instance = new KTInputNumber(wrap);
|
|
124
|
+
const spy = vi.fn();
|
|
125
|
+
wrap.addEventListener('kt.input-number.change', spy);
|
|
126
|
+
|
|
127
|
+
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
128
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
129
|
+
expect(spy.mock.calls[0][0].detail.payload.value).toBe(7);
|
|
130
|
+
|
|
131
|
+
instance.dispose();
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('uses null value when input is empty', () => {
|
|
135
|
+
const wrap = document.createElement('div');
|
|
136
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
137
|
+
const input = document.createElement('input');
|
|
138
|
+
input.type = 'number';
|
|
139
|
+
input.value = '';
|
|
140
|
+
wrap.appendChild(input);
|
|
141
|
+
container.appendChild(wrap);
|
|
142
|
+
|
|
143
|
+
const instance = new KTInputNumber(wrap);
|
|
144
|
+
const spy = vi.fn();
|
|
145
|
+
wrap.addEventListener('kt.input-number.input', spy);
|
|
146
|
+
|
|
147
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
148
|
+
expect(spy.mock.calls[0][0].detail.payload).toMatchObject({
|
|
149
|
+
value: null,
|
|
150
|
+
valueAsString: '',
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
instance.dispose();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('omits step in payload when step="any"', () => {
|
|
157
|
+
const wrap = document.createElement('div');
|
|
158
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
159
|
+
const input = document.createElement('input');
|
|
160
|
+
input.type = 'number';
|
|
161
|
+
input.min = '0';
|
|
162
|
+
input.max = '10';
|
|
163
|
+
input.step = 'any';
|
|
164
|
+
input.value = '3';
|
|
165
|
+
wrap.appendChild(input);
|
|
166
|
+
container.appendChild(wrap);
|
|
167
|
+
|
|
168
|
+
new KTInputNumber(wrap);
|
|
169
|
+
const spy = vi.fn();
|
|
170
|
+
wrap.addEventListener('kt.input-number.input', spy);
|
|
171
|
+
|
|
172
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
173
|
+
expect(spy.mock.calls[0][0].detail.payload.step).toBeUndefined();
|
|
174
|
+
|
|
175
|
+
KTInputNumber.getInstance(wrap)?.dispose();
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
describe('increment and decrement', () => {
|
|
180
|
+
it('stepUp increases value by step within max', () => {
|
|
181
|
+
const wrap = document.createElement('div');
|
|
182
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
183
|
+
const input = document.createElement('input');
|
|
184
|
+
input.type = 'number';
|
|
185
|
+
input.min = '0';
|
|
186
|
+
input.max = '10';
|
|
187
|
+
input.step = '2';
|
|
188
|
+
input.value = '4';
|
|
189
|
+
const inc = document.createElement('button');
|
|
190
|
+
inc.type = 'button';
|
|
191
|
+
inc.setAttribute('data-kt-input-number-increment', 'true');
|
|
192
|
+
wrap.appendChild(inc);
|
|
193
|
+
wrap.appendChild(input);
|
|
194
|
+
container.appendChild(wrap);
|
|
195
|
+
|
|
196
|
+
const instance = new KTInputNumber(wrap);
|
|
197
|
+
inc.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
198
|
+
expect(input.value).toBe('6');
|
|
199
|
+
instance.dispose();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('stepDown decreases value by step within min', () => {
|
|
203
|
+
const wrap = document.createElement('div');
|
|
204
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
205
|
+
const input = document.createElement('input');
|
|
206
|
+
input.type = 'number';
|
|
207
|
+
input.min = '0';
|
|
208
|
+
input.max = '10';
|
|
209
|
+
input.step = '3';
|
|
210
|
+
input.value = '6';
|
|
211
|
+
const dec = document.createElement('button');
|
|
212
|
+
dec.type = 'button';
|
|
213
|
+
dec.setAttribute('data-kt-input-number-decrement', 'true');
|
|
214
|
+
wrap.appendChild(dec);
|
|
215
|
+
wrap.appendChild(input);
|
|
216
|
+
container.appendChild(wrap);
|
|
217
|
+
|
|
218
|
+
const instance = new KTInputNumber(wrap);
|
|
219
|
+
dec.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
220
|
+
expect(input.value).toBe('3');
|
|
221
|
+
instance.dispose();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('does not adjust when input is disabled', () => {
|
|
225
|
+
const wrap = document.createElement('div');
|
|
226
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
227
|
+
const input = document.createElement('input');
|
|
228
|
+
input.type = 'number';
|
|
229
|
+
input.min = '0';
|
|
230
|
+
input.max = '10';
|
|
231
|
+
input.value = '5';
|
|
232
|
+
input.disabled = true;
|
|
233
|
+
const inc = document.createElement('button');
|
|
234
|
+
inc.type = 'button';
|
|
235
|
+
inc.setAttribute('data-kt-input-number-increment', 'true');
|
|
236
|
+
wrap.appendChild(inc);
|
|
237
|
+
wrap.appendChild(input);
|
|
238
|
+
container.appendChild(wrap);
|
|
239
|
+
|
|
240
|
+
const instance = new KTInputNumber(wrap);
|
|
241
|
+
inc.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
242
|
+
expect(input.value).toBe('5');
|
|
243
|
+
instance.dispose();
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
describe('dispose', () => {
|
|
248
|
+
it('removes listeners and clears instance', () => {
|
|
249
|
+
const wrap = document.createElement('div');
|
|
250
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
251
|
+
const input = document.createElement('input');
|
|
252
|
+
input.type = 'number';
|
|
253
|
+
input.value = '1';
|
|
254
|
+
wrap.appendChild(input);
|
|
255
|
+
container.appendChild(wrap);
|
|
256
|
+
|
|
257
|
+
const instance = new KTInputNumber(wrap);
|
|
258
|
+
instance.dispose();
|
|
259
|
+
expect(KTInputNumber.getInstance(wrap)).toBeNull();
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
describe('createInstances', () => {
|
|
264
|
+
it('skips lazy roots', () => {
|
|
265
|
+
const wrap = document.createElement('div');
|
|
266
|
+
wrap.setAttribute('data-kt-input-number', 'true');
|
|
267
|
+
wrap.setAttribute('data-kt-input-number-lazy', 'true');
|
|
268
|
+
const input = document.createElement('input');
|
|
269
|
+
input.type = 'number';
|
|
270
|
+
input.value = '1';
|
|
271
|
+
wrap.appendChild(input);
|
|
272
|
+
container.appendChild(wrap);
|
|
273
|
+
|
|
274
|
+
KTInputNumber.createInstances();
|
|
275
|
+
expect(KTInputNumber.getInstance(wrap)).toBeNull();
|
|
276
|
+
});
|
|
277
|
+
});
|
|
278
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KTUI - Free & Open-Source Tailwind UI Components by Keenthemes
|
|
3
|
+
* Copyright 2025 by Keenthemes Inc
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { KTInputNumber } from './input-number';
|
|
7
|
+
export type {
|
|
8
|
+
KTInputNumberConfigInterface,
|
|
9
|
+
KTInputNumberEventPayloadInterface,
|
|
10
|
+
KTInputNumberInterface,
|
|
11
|
+
} from './types';
|