@lemonadejs/dropdown 3.6.2 → 5.2.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 +3 -3
- package/dist/index.d.ts +36 -15
- package/dist/index.js +494 -285
- package/dist/style.css +51 -21
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# JavaScript Dropdown
|
|
2
2
|
|
|
3
|
-
[
|
|
3
|
+
[The Dropdown Documentation](https://lemonadejs.com/docs/plugins/dropdown)
|
|
4
4
|
|
|
5
|
-
Compatible with Vanilla JavaScript, LemonadeJS, React,
|
|
5
|
+
Compatible with Vanilla JavaScript, LemonadeJS, React, VueJS or Angular.
|
|
6
6
|
|
|
7
7
|
The LemonadeJS Dropdown is a versatile solution for efficient option management. It is a framework-agnostic JavaScript plugin designed for seamless integration with Vue, React, and Angular. This feature-rich dropdown incorporates autocomplete for swift selections, grouping for organized options, and lazy loading for optimized performance, contributing to a smooth and improved user experience.
|
|
8
8
|
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
declare function Dropdown(el: HTMLElement, options?: Dropdown.Options): Dropdown.Instance;
|
|
8
8
|
|
|
9
9
|
declare namespace Dropdown {
|
|
10
|
+
|
|
10
11
|
interface Item {
|
|
11
12
|
/** Value of the selected item. */
|
|
12
13
|
value?: string | number;
|
|
@@ -35,8 +36,8 @@ declare namespace Dropdown {
|
|
|
35
36
|
multiple?: boolean;
|
|
36
37
|
/** Enables the autocomplete feature for user input */
|
|
37
38
|
autocomplete?: boolean;
|
|
38
|
-
/** Rendering style of the dropdown: 'default', 'picker', 'searchbar' or inline */
|
|
39
|
-
type?: 'default' | 'picker' | 'searchbar' | 'inline',
|
|
39
|
+
/** Rendering style of the dropdown: 'default', 'picker', 'searchbar' or inline. auto will render picker or searchbar based on screensize */
|
|
40
|
+
type?: 'default' | 'auto' | 'picker' | 'searchbar' | 'inline',
|
|
40
41
|
/** Defines the dropdown width */
|
|
41
42
|
width?: number;
|
|
42
43
|
/** The initial value of the dropdown */
|
|
@@ -45,18 +46,20 @@ declare namespace Dropdown {
|
|
|
45
46
|
placeholder?: string;
|
|
46
47
|
/** Allow insert new items */
|
|
47
48
|
insert?: boolean;
|
|
48
|
-
/** Specifies the URL for fetching the data
|
|
49
|
+
/** Specifies the URL for fetching the data */
|
|
49
50
|
url?: string;
|
|
51
|
+
/** Enables another ways to option insert */
|
|
52
|
+
prompt?: boolean | string | (() => string);
|
|
50
53
|
/** Allow empty. Default: true */
|
|
51
|
-
|
|
54
|
+
allowEmpty?: boolean;
|
|
52
55
|
/** Event handler for value changes */
|
|
53
|
-
onchange?: (
|
|
56
|
+
onchange?: (self: object, newValue: string|number) => void;
|
|
54
57
|
/** Event handler for when the dropdown is ready */
|
|
55
|
-
onload?: (
|
|
58
|
+
onload?: (self: object) => void;
|
|
56
59
|
/** Event handler for when the dropdown opens */
|
|
57
|
-
onopen?: (
|
|
60
|
+
onopen?: (self: object) => void;
|
|
58
61
|
/** Event handler for when the dropdown closes */
|
|
59
|
-
onclose?: (
|
|
62
|
+
onclose?: (self: object) => void;
|
|
60
63
|
/**
|
|
61
64
|
* Event handler for just before a new option is added to the dropdown. This is an async function to handle ajax requests.
|
|
62
65
|
* Example:
|
|
@@ -69,20 +72,38 @@ declare namespace Dropdown {
|
|
|
69
72
|
* }
|
|
70
73
|
*
|
|
71
74
|
* */
|
|
72
|
-
onbeforeinsert?: (
|
|
75
|
+
onbeforeinsert?: (self: object, item: Item) => boolean | void;
|
|
73
76
|
/** Event handler for when a new option is added to the dropdown */
|
|
74
|
-
oninsert?: (
|
|
77
|
+
oninsert?: (self: object, item: Item) => void;
|
|
75
78
|
/** Before the search happens */
|
|
76
|
-
onbeforesearch?: (
|
|
79
|
+
onbeforesearch?: (self: object, query: string, result: object[]) => boolean | null;
|
|
77
80
|
/** Event handler for processing search results */
|
|
78
|
-
onsearch?: (
|
|
81
|
+
onsearch?: (self: object, query: string, result: object[]) => void;
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
interface Instance {
|
|
82
85
|
/** Internal type */
|
|
83
|
-
type: '
|
|
84
|
-
/**
|
|
85
|
-
value
|
|
86
|
+
type: 'default' | 'auto' | 'picker' | 'searchbar' | 'inline';
|
|
87
|
+
/** The initial value of the dropdown */
|
|
88
|
+
value?: string | string[] | number | number[];
|
|
89
|
+
/** Existing data */
|
|
90
|
+
data: Item[];
|
|
91
|
+
/** Add a new item */
|
|
92
|
+
add: (item: Item) => void;
|
|
93
|
+
/** Open dropdown */
|
|
94
|
+
open: () => void;
|
|
95
|
+
/** Close Dropdown */
|
|
96
|
+
close: () => void;
|
|
97
|
+
/** Dropdown state */
|
|
98
|
+
isClosed: () => boolean;
|
|
99
|
+
/** Get current value */
|
|
100
|
+
getValue: () => number | string | number[] | string[];
|
|
101
|
+
/** Get current value */
|
|
102
|
+
setValue: (value: number | string | number[] | string[]) => void;
|
|
103
|
+
/** Get current data */
|
|
104
|
+
getData: () => Item[];
|
|
105
|
+
/** Set current data */
|
|
106
|
+
setData: (data: Item[]) => void;
|
|
86
107
|
}
|
|
87
108
|
}
|
|
88
109
|
|
package/dist/index.js
CHANGED
|
@@ -17,36 +17,80 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
17
17
|
global.Dropdown = factory();
|
|
18
18
|
}(this, (function () {
|
|
19
19
|
|
|
20
|
+
class CustomEvents extends Event {
|
|
21
|
+
constructor(type, props, options) {
|
|
22
|
+
super(type, {
|
|
23
|
+
bubbles: true,
|
|
24
|
+
composed: true,
|
|
25
|
+
...options,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
if (props) {
|
|
29
|
+
for (const key in props) {
|
|
30
|
+
// Avoid assigning if property already exists anywhere on `this`
|
|
31
|
+
if (! (key in this)) {
|
|
32
|
+
this[key] = props[key];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Dispatcher
|
|
40
|
+
const Dispatch = function(method, type, options) {
|
|
41
|
+
// Try calling the method directly if provided
|
|
42
|
+
if (typeof method === 'function') {
|
|
43
|
+
let a = Object.values(options);
|
|
44
|
+
return method(...a);
|
|
45
|
+
} else if (this.tagName) {
|
|
46
|
+
this.dispatchEvent(new CustomEvents(type, options));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
20
50
|
// Default row height
|
|
21
51
|
let defaultRowHeight = 24;
|
|
22
52
|
|
|
53
|
+
// Translations
|
|
54
|
+
const T = function(t) {
|
|
55
|
+
if (typeof(document) !== "undefined" && document.dictionary) {
|
|
56
|
+
return document.dictionary[t] || t;
|
|
57
|
+
} else {
|
|
58
|
+
return t;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const isEmpty = function(v) {
|
|
63
|
+
return v === '' || v === null || v === undefined || (Array.isArray(v) && v.length === 0);
|
|
64
|
+
}
|
|
65
|
+
|
|
23
66
|
/**
|
|
24
|
-
* Compare two arrays
|
|
25
|
-
*
|
|
26
|
-
* @param {
|
|
67
|
+
* Compare two values (arrays, strings, numbers, etc.)
|
|
68
|
+
* Returns true if both are equal or empty
|
|
69
|
+
* @param {*} a1
|
|
70
|
+
* @param {*} a2
|
|
27
71
|
*/
|
|
28
|
-
const compareValues = function
|
|
72
|
+
const compareValues = function(a1, a2) {
|
|
73
|
+
if (a1 === a2 || (isEmpty(a1) && isEmpty(a2))) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
29
77
|
if (!a1 || !a2) {
|
|
30
78
|
return false;
|
|
31
79
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} else {
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
let i = a1.length;
|
|
40
|
-
if (i !== a2.length) {
|
|
80
|
+
|
|
81
|
+
if (Array.isArray(a1) && Array.isArray(a2)) {
|
|
82
|
+
if (a1.length !== a2.length) {
|
|
41
83
|
return false;
|
|
42
84
|
}
|
|
43
|
-
|
|
85
|
+
for (let i = 0; i < a1.length; i++) {
|
|
44
86
|
if (a1[i] !== a2[i]) {
|
|
45
87
|
return false;
|
|
46
88
|
}
|
|
47
89
|
}
|
|
90
|
+
return true;
|
|
48
91
|
}
|
|
49
|
-
|
|
92
|
+
|
|
93
|
+
return a1 === a2;
|
|
50
94
|
}
|
|
51
95
|
|
|
52
96
|
const lazyLoading = function (self) {
|
|
@@ -303,7 +347,24 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
303
347
|
return data;
|
|
304
348
|
}
|
|
305
349
|
|
|
306
|
-
const
|
|
350
|
+
const isDOM = function(o) {
|
|
351
|
+
return (o instanceof Element || o instanceof HTMLDocument || o instanceof DocumentFragment);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const compatibilityMapping = function(s) {
|
|
355
|
+
const props = {
|
|
356
|
+
newOptions: 'insert',
|
|
357
|
+
allowempty: 'allowEmpty'
|
|
358
|
+
}
|
|
359
|
+
Object.keys(props).forEach((k) => {
|
|
360
|
+
if (typeof(s[k]) !== 'undefined') {
|
|
361
|
+
s[props[k]] = s[k];
|
|
362
|
+
delete s[k];
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
const Dropdown = function (children, { onchange, onload }) {
|
|
307
368
|
let self = this;
|
|
308
369
|
// Data
|
|
309
370
|
let data = [];
|
|
@@ -313,12 +374,13 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
313
374
|
let cursor = null;
|
|
314
375
|
// Control events
|
|
315
376
|
let ignoreEvents = false;
|
|
316
|
-
// Default width
|
|
317
|
-
if (! self.width) {
|
|
318
|
-
self.width = 260;
|
|
319
|
-
}
|
|
320
377
|
// Lazy loading global instance
|
|
321
378
|
let lazyloading = null;
|
|
379
|
+
// Tracking changes
|
|
380
|
+
let changesDetected = false;
|
|
381
|
+
|
|
382
|
+
// Compatibility with jSuites
|
|
383
|
+
compatibilityMapping(self);
|
|
322
384
|
|
|
323
385
|
// Data
|
|
324
386
|
if (! Array.isArray(self.data)) {
|
|
@@ -332,16 +394,20 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
332
394
|
})
|
|
333
395
|
}
|
|
334
396
|
|
|
397
|
+
// Decide the type based on the size of the screen
|
|
398
|
+
let autoType = self.type === 'auto';
|
|
399
|
+
|
|
335
400
|
// Custom events defined by the user
|
|
336
|
-
let
|
|
337
|
-
|
|
401
|
+
let load = self.onload;
|
|
402
|
+
self.onload = null;
|
|
403
|
+
let change = self.onchange;
|
|
404
|
+
self.onchange = null;
|
|
338
405
|
|
|
339
406
|
// Cursor controllers
|
|
340
407
|
const setCursor = function (index, force) {
|
|
341
408
|
let item = self.rows[index];
|
|
342
|
-
|
|
343
409
|
if (typeof (item) !== 'undefined') {
|
|
344
|
-
// Set cursor number
|
|
410
|
+
// Set the cursor number
|
|
345
411
|
cursor = index;
|
|
346
412
|
// Set visual indication
|
|
347
413
|
item.cursor = true;
|
|
@@ -405,13 +471,36 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
405
471
|
setCursor(cursor);
|
|
406
472
|
}
|
|
407
473
|
|
|
408
|
-
const
|
|
474
|
+
const adjustDimensions = function(data) {
|
|
409
475
|
// Estimate width
|
|
410
|
-
let width = self.width;
|
|
476
|
+
let width = self.width ?? 0;
|
|
477
|
+
// Adjust the width
|
|
478
|
+
let w = getInput().offsetWidth;
|
|
479
|
+
if (width < w) {
|
|
480
|
+
width = w;
|
|
481
|
+
}
|
|
482
|
+
// Width && values
|
|
483
|
+
data.map(function (s) {
|
|
484
|
+
// Estimated width of the element
|
|
485
|
+
if (s.text) {
|
|
486
|
+
let w = Math.max(width, s.text.length * 7.5);
|
|
487
|
+
if (width < w) {
|
|
488
|
+
width = w;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
// Min width for the container
|
|
493
|
+
self.container.parentNode.style.width = (width - 2) + 'px';
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const setData = function () {
|
|
411
497
|
// Data
|
|
412
498
|
data = JSON.parse(JSON.stringify(self.data));
|
|
413
499
|
// Re-order to make sure groups are in sequence
|
|
414
500
|
if (data && data.length) {
|
|
501
|
+
// Adjust width and height
|
|
502
|
+
adjustDimensions(data);
|
|
503
|
+
// Groups
|
|
415
504
|
data.sort((a, b) => {
|
|
416
505
|
// Compare groups
|
|
417
506
|
if (a.group && b.group) {
|
|
@@ -428,33 +517,6 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
428
517
|
group = v.group;
|
|
429
518
|
}
|
|
430
519
|
});
|
|
431
|
-
// Width && values
|
|
432
|
-
data.map(function (s) {
|
|
433
|
-
// Estimated width of the element
|
|
434
|
-
if (s.text) {
|
|
435
|
-
width = Math.max(width, s.text.length * 8);
|
|
436
|
-
}
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
// Adjust the width
|
|
440
|
-
if (typeof(self.width) === 'undefined') {
|
|
441
|
-
let w = self.input.offsetWidth;
|
|
442
|
-
if (width < w) {
|
|
443
|
-
width = w;
|
|
444
|
-
}
|
|
445
|
-
// Estimated with based on the text
|
|
446
|
-
if (self.width < width) {
|
|
447
|
-
self.width = width;
|
|
448
|
-
}
|
|
449
|
-
self.el.style.width = self.width + 'px';
|
|
450
|
-
}
|
|
451
|
-
// Min width for the container
|
|
452
|
-
self.container.parentNode.style.minWidth = self.width + 'px';
|
|
453
|
-
// Height
|
|
454
|
-
self.height = 400;
|
|
455
|
-
// Animation for mobile
|
|
456
|
-
if (document.documentElement.clientWidth < 800) {
|
|
457
|
-
self.animation = true;
|
|
458
520
|
}
|
|
459
521
|
// Data to be listed
|
|
460
522
|
self.rows = data;
|
|
@@ -462,18 +524,18 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
462
524
|
|
|
463
525
|
const updateLabel = function () {
|
|
464
526
|
if (value && value.length) {
|
|
465
|
-
|
|
527
|
+
getInput().textContent = value.filter(v => v.selected).map(i => i.text).join('; ');
|
|
466
528
|
} else {
|
|
467
|
-
|
|
529
|
+
getInput().textContent = '';
|
|
468
530
|
}
|
|
469
531
|
}
|
|
470
532
|
|
|
471
533
|
const setValue = function (v, ignoreEvent) {
|
|
472
534
|
// Values
|
|
473
535
|
let newValue;
|
|
474
|
-
if (!Array.isArray(v)) {
|
|
475
|
-
if (typeof
|
|
476
|
-
newValue = v.split(';');
|
|
536
|
+
if (! Array.isArray(v)) {
|
|
537
|
+
if (typeof(v) === 'string') {
|
|
538
|
+
newValue = v.split(self.divisor ?? ';');
|
|
477
539
|
} else {
|
|
478
540
|
newValue = [v];
|
|
479
541
|
}
|
|
@@ -486,12 +548,9 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
486
548
|
|
|
487
549
|
if (Array.isArray(data)) {
|
|
488
550
|
data.map(function (s) {
|
|
489
|
-
|
|
490
|
-
if (
|
|
491
|
-
s.selected = true;
|
|
551
|
+
s.selected = newValue.some(v => v == s.value);
|
|
552
|
+
if (s.selected) {
|
|
492
553
|
value.push(s);
|
|
493
|
-
} else {
|
|
494
|
-
s.selected = false;
|
|
495
554
|
}
|
|
496
555
|
});
|
|
497
556
|
}
|
|
@@ -500,8 +559,11 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
500
559
|
updateLabel();
|
|
501
560
|
|
|
502
561
|
// Component onchange
|
|
503
|
-
if (! ignoreEvent
|
|
504
|
-
|
|
562
|
+
if (! ignoreEvent) {
|
|
563
|
+
Dispatch.call(self, change, 'change', {
|
|
564
|
+
instance: self,
|
|
565
|
+
value: getValue(),
|
|
566
|
+
});
|
|
505
567
|
}
|
|
506
568
|
}
|
|
507
569
|
|
|
@@ -520,38 +582,6 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
520
582
|
}
|
|
521
583
|
}
|
|
522
584
|
|
|
523
|
-
const onclose = function () {
|
|
524
|
-
// Cursor
|
|
525
|
-
removeCursor(true);
|
|
526
|
-
// Reset search
|
|
527
|
-
if (self.autocomplete) {
|
|
528
|
-
// Go to begin of the data
|
|
529
|
-
self.rows = data;
|
|
530
|
-
// Remove editable attribute
|
|
531
|
-
self.input.removeAttribute('contenteditable');
|
|
532
|
-
// Clear input
|
|
533
|
-
self.input.textContent = '';
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// Current value
|
|
537
|
-
let newValue = getValue();
|
|
538
|
-
|
|
539
|
-
// If that is different from the component value
|
|
540
|
-
if (!compareValues(newValue, self.value)) {
|
|
541
|
-
self.value = newValue;
|
|
542
|
-
} else {
|
|
543
|
-
// Update label
|
|
544
|
-
updateLabel();
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
// Identify the new state of the dropdown
|
|
548
|
-
self.state = false;
|
|
549
|
-
|
|
550
|
-
if (typeof (self.onclose) === 'function') {
|
|
551
|
-
self.onclose(self);
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
585
|
const onopen = function () {
|
|
556
586
|
self.state = true;
|
|
557
587
|
// Value
|
|
@@ -567,17 +597,64 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
567
597
|
}
|
|
568
598
|
// Prepare search field
|
|
569
599
|
if (self.autocomplete) {
|
|
570
|
-
//
|
|
571
|
-
|
|
600
|
+
// Get the input
|
|
601
|
+
let input = getInput();
|
|
572
602
|
// Editable
|
|
573
|
-
|
|
603
|
+
input.setAttribute('contenteditable', true);
|
|
604
|
+
// Clear input
|
|
605
|
+
input.textContent = '';
|
|
574
606
|
// Focus on the item
|
|
575
|
-
|
|
607
|
+
input.focus();
|
|
608
|
+
}
|
|
609
|
+
// Adjust width and height
|
|
610
|
+
adjustDimensions(self.data);
|
|
611
|
+
// Open event
|
|
612
|
+
Dispatch.call(self, self.onopen, 'open', {
|
|
613
|
+
instance: self
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const onclose = function (options, origin) {
|
|
618
|
+
// Cursor
|
|
619
|
+
removeCursor(true);
|
|
620
|
+
// Reset search
|
|
621
|
+
if (self.autocomplete) {
|
|
622
|
+
// Go to begin of the data
|
|
623
|
+
self.rows = data;
|
|
624
|
+
// Get the input
|
|
625
|
+
let input = getInput();
|
|
626
|
+
if (input) {
|
|
627
|
+
// Remove editable attribute
|
|
628
|
+
input.removeAttribute('contenteditable');
|
|
629
|
+
// Clear input
|
|
630
|
+
input.textContent = '';
|
|
631
|
+
}
|
|
576
632
|
}
|
|
577
633
|
|
|
578
|
-
if (
|
|
579
|
-
|
|
634
|
+
if (origin === 'escape') {
|
|
635
|
+
// Cancel operation and keep the same previous value
|
|
636
|
+
setValue(self.value, true);
|
|
637
|
+
} else {
|
|
638
|
+
// Current value
|
|
639
|
+
let newValue = getValue();
|
|
640
|
+
|
|
641
|
+
// If that is different from the component value
|
|
642
|
+
if (changesDetected === true && ! compareValues(newValue, self.value)) {
|
|
643
|
+
self.value = newValue;
|
|
644
|
+
} else {
|
|
645
|
+
// Update label
|
|
646
|
+
updateLabel();
|
|
647
|
+
}
|
|
580
648
|
}
|
|
649
|
+
|
|
650
|
+
// Identify the new state of the dropdown
|
|
651
|
+
self.state = false;
|
|
652
|
+
|
|
653
|
+
// Close event
|
|
654
|
+
Dispatch.call(self, self.onclose, 'close', {
|
|
655
|
+
instance: self,
|
|
656
|
+
...options
|
|
657
|
+
});
|
|
581
658
|
}
|
|
582
659
|
|
|
583
660
|
const loadData = function(result) {
|
|
@@ -595,31 +672,210 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
595
672
|
if (typeof(self.value) !== 'undefined') {
|
|
596
673
|
setValue(self.value, true);
|
|
597
674
|
}
|
|
598
|
-
//
|
|
599
|
-
|
|
600
|
-
|
|
675
|
+
// Onload method
|
|
676
|
+
Dispatch.call(self, load, 'load', {
|
|
677
|
+
instance: self
|
|
678
|
+
});
|
|
679
|
+
// Remove loading spin
|
|
680
|
+
self.el.classList.remove('lm-dropdown-loading');
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
const getInput = function() {
|
|
684
|
+
return self.input;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
const search = function(str) {
|
|
688
|
+
if (! self.isClosed() && self.autocomplete) {
|
|
689
|
+
// Filter options
|
|
690
|
+
let temp;
|
|
691
|
+
|
|
692
|
+
const find = (prop) => {
|
|
693
|
+
return prop && prop.toString().toLowerCase().includes(str);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
if (! str) {
|
|
697
|
+
temp = data;
|
|
698
|
+
} else {
|
|
699
|
+
temp = data.filter(item => {
|
|
700
|
+
return item.selected === true || find(item.text) || find(item.group) || find(item.keywords);
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
let ret = Dispatch.call(self, self.onbeforesearch, 'beforesearch', {
|
|
705
|
+
instance: self,
|
|
706
|
+
query: str,
|
|
707
|
+
result: temp,
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
if (typeof(ret) !== 'undefined') {
|
|
711
|
+
if (ret === false) {
|
|
712
|
+
} else if (Array.isArray(ret)) {
|
|
713
|
+
temp = ret;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Cursor
|
|
718
|
+
removeCursor(true);
|
|
719
|
+
// Update the data from the dropdown
|
|
720
|
+
self.rows = temp;
|
|
721
|
+
// Event
|
|
722
|
+
Dispatch.call(self, self.onsearch, 'search', {
|
|
723
|
+
instance: self,
|
|
724
|
+
query: str,
|
|
725
|
+
result: temp,
|
|
726
|
+
});
|
|
601
727
|
}
|
|
602
728
|
}
|
|
603
729
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
730
|
+
const events = {
|
|
731
|
+
focusout: (e) => {
|
|
732
|
+
if (self.modal) {
|
|
733
|
+
if (! (e.relatedTarget && self.el.contains(e.relatedTarget))) {
|
|
734
|
+
if (! self.isClosed()) {
|
|
735
|
+
self.close({ origin: 'focusout '});
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
},
|
|
740
|
+
keydown: (e) => {
|
|
741
|
+
if (! self.isClosed()) {
|
|
742
|
+
let prevent = false;
|
|
743
|
+
if (e.code === 'ArrowUp') {
|
|
744
|
+
moveCursor(-1);
|
|
745
|
+
prevent = true;
|
|
746
|
+
} else if (e.code === 'ArrowDown') {
|
|
747
|
+
moveCursor(1);
|
|
748
|
+
prevent = true;
|
|
749
|
+
} else if (e.code === 'Home') {
|
|
750
|
+
moveCursor(-1, true);
|
|
751
|
+
if (!self.autocomplete) {
|
|
752
|
+
prevent = true;
|
|
753
|
+
}
|
|
754
|
+
} else if (e.code === 'End') {
|
|
755
|
+
moveCursor(1, true);
|
|
756
|
+
if (!self.autocomplete) {
|
|
757
|
+
prevent = true;
|
|
758
|
+
}
|
|
759
|
+
} else if (e.code === 'Enter') {
|
|
760
|
+
if (e.target.tagName === 'BUTTON') {
|
|
761
|
+
e.target.click();
|
|
762
|
+
let input = getInput();
|
|
763
|
+
input.focus();
|
|
764
|
+
} else {
|
|
765
|
+
select(e, self.rows[cursor]);
|
|
766
|
+
}
|
|
767
|
+
prevent = true;
|
|
768
|
+
} else if (e.code === 'Escape') {
|
|
769
|
+
self.close({ origin: 'escape'});
|
|
770
|
+
prevent = true;
|
|
771
|
+
} else {
|
|
772
|
+
if (e.keyCode === 32 && !self.autocomplete) {
|
|
773
|
+
select(e, self.rows[cursor]);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
if (prevent) {
|
|
778
|
+
e.preventDefault();
|
|
779
|
+
e.stopImmediatePropagation();
|
|
780
|
+
}
|
|
781
|
+
} else {
|
|
782
|
+
if (e.code === 'ArrowUp' || e.code === 'ArrowDown' || e.code === 'Enter') {
|
|
783
|
+
self.open();
|
|
784
|
+
e.preventDefault();
|
|
785
|
+
e.stopImmediatePropagation();
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
mousedown: (e) => {
|
|
790
|
+
if (e.target.classList.contains('lm-dropdown-input')) {
|
|
791
|
+
if (self.autocomplete) {
|
|
792
|
+
let x;
|
|
793
|
+
if (e.changedTouches && e.changedTouches[0]) {
|
|
794
|
+
x = e.changedTouches[0].clientX;
|
|
795
|
+
} else {
|
|
796
|
+
x = e.clientX;
|
|
797
|
+
}
|
|
798
|
+
if (e.target.offsetWidth - (x - e.target.offsetLeft) < 20) {
|
|
799
|
+
toggle();
|
|
800
|
+
} else {
|
|
801
|
+
self.open();
|
|
802
|
+
}
|
|
803
|
+
} else {
|
|
804
|
+
toggle();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
},
|
|
808
|
+
paste: (e) => {
|
|
809
|
+
if (e.target.classList.contains('lm-dropdown-input')) {
|
|
810
|
+
let text;
|
|
811
|
+
if (e.clipboardData || e.originalEvent.clipboardData) {
|
|
812
|
+
text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
|
813
|
+
} else if (window.clipboardData) {
|
|
814
|
+
text = window.clipboardData.getData('Text');
|
|
815
|
+
}
|
|
816
|
+
text = text.replace(/(\r\n|\n|\r)/gm, "");
|
|
817
|
+
document.execCommand('insertText', false, text)
|
|
818
|
+
e.preventDefault();
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
input: (e) => {
|
|
822
|
+
if (e.target.classList.contains('lm-dropdown-input')) {
|
|
823
|
+
search(e.target.textContent.toLowerCase());
|
|
824
|
+
}
|
|
825
|
+
},
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
const selectItem = function(s) {
|
|
829
|
+
if (self.multiple === true) {
|
|
830
|
+
let position = value.indexOf(s);
|
|
831
|
+
if (position === -1) {
|
|
832
|
+
value.push(s);
|
|
833
|
+
s.selected = true;
|
|
834
|
+
} else {
|
|
835
|
+
value.splice(position, 1);
|
|
836
|
+
s.selected = false;
|
|
837
|
+
}
|
|
838
|
+
} else {
|
|
839
|
+
if (value[0] === s) {
|
|
840
|
+
if (self.allowEmpty === false) {
|
|
841
|
+
s.selected = true;
|
|
842
|
+
} else {
|
|
843
|
+
s.selected = !s.selected;
|
|
844
|
+
}
|
|
845
|
+
} else {
|
|
846
|
+
if (value[0]) {
|
|
847
|
+
value[0].selected = false;
|
|
848
|
+
}
|
|
849
|
+
s.selected = true;
|
|
850
|
+
}
|
|
851
|
+
if (s.selected) {
|
|
852
|
+
value = [s];
|
|
853
|
+
} else {
|
|
854
|
+
value = [];
|
|
855
|
+
}
|
|
607
856
|
}
|
|
608
857
|
|
|
609
|
-
|
|
858
|
+
changesDetected = true;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
const add = async function (e) {
|
|
862
|
+
let input = getInput();
|
|
863
|
+
let text = input.textContent;
|
|
864
|
+
if (! text) {
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
610
867
|
|
|
611
868
|
// New item
|
|
612
869
|
let s = {
|
|
613
|
-
text:
|
|
614
|
-
value:
|
|
870
|
+
text: text,
|
|
871
|
+
value: text,
|
|
615
872
|
}
|
|
616
873
|
|
|
617
874
|
// Event
|
|
618
|
-
if (typeof
|
|
619
|
-
|
|
620
|
-
elClass.add('lm-dropdown-loading');
|
|
875
|
+
if (typeof(self.onbeforeinsert) === 'function') {
|
|
876
|
+
self.el.classList.add('lm-dropdown-loading');
|
|
621
877
|
let ret = await self.onbeforeinsert(self, s);
|
|
622
|
-
|
|
878
|
+
self.el.classList.remove('lm-dropdown-loading');
|
|
623
879
|
if (ret === false) {
|
|
624
880
|
return;
|
|
625
881
|
} else if (ret) {
|
|
@@ -627,125 +883,117 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
627
883
|
}
|
|
628
884
|
}
|
|
629
885
|
|
|
630
|
-
|
|
631
|
-
data.unshift(s);
|
|
632
|
-
// Select the new item
|
|
633
|
-
self.select(e, s);
|
|
634
|
-
// Close dropdown
|
|
635
|
-
self.search();
|
|
886
|
+
self.add(s);
|
|
636
887
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
888
|
+
e.preventDefault();
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
const select = function (e, s) {
|
|
892
|
+
if (s) {
|
|
893
|
+
selectItem(s);
|
|
894
|
+
// Close the modal
|
|
895
|
+
if (self.multiple !== true) {
|
|
896
|
+
self.close({ origin: 'button' });
|
|
897
|
+
}
|
|
640
898
|
}
|
|
641
899
|
}
|
|
642
900
|
|
|
643
|
-
|
|
644
|
-
if (self.
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
let value = self.input.textContent.toLowerCase()
|
|
648
|
-
if (! value) {
|
|
649
|
-
temp = data;
|
|
901
|
+
const toggle = function () {
|
|
902
|
+
if (self.modal) {
|
|
903
|
+
if (self.isClosed()) {
|
|
904
|
+
self.open();
|
|
650
905
|
} else {
|
|
651
|
-
|
|
652
|
-
return item.selected === true ||
|
|
653
|
-
(item.text.toLowerCase().includes(value)) ||
|
|
654
|
-
(item.group && item.group.toLowerCase().includes(value)) ||
|
|
655
|
-
(item.keywords.toLowerCase().includes(value));
|
|
656
|
-
});
|
|
906
|
+
self.close({ origin: 'button' });
|
|
657
907
|
}
|
|
658
|
-
// Cursor
|
|
659
|
-
removeCursor(true);
|
|
660
|
-
// Update the data from the dropdown
|
|
661
|
-
self.rows = temp;
|
|
662
908
|
}
|
|
663
909
|
}
|
|
664
910
|
|
|
665
|
-
self.
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
911
|
+
self.add = function (newItem) {
|
|
912
|
+
// Process the data
|
|
913
|
+
data.unshift(newItem);
|
|
914
|
+
|
|
915
|
+
// Refresh screen
|
|
916
|
+
self.result.unshift(newItem);
|
|
917
|
+
self.rows.unshift(newItem);
|
|
918
|
+
self.refresh('result');
|
|
919
|
+
|
|
920
|
+
Dispatch.call(self, self.oninsert, 'insert', {
|
|
921
|
+
instance: self,
|
|
922
|
+
item: newItem,
|
|
923
|
+
});
|
|
670
924
|
}
|
|
671
925
|
|
|
672
|
-
self.
|
|
673
|
-
// Close the modal
|
|
926
|
+
self.open = function () {
|
|
674
927
|
if (self.modal) {
|
|
675
|
-
self.
|
|
928
|
+
if (self.isClosed()) {
|
|
929
|
+
if (autoType) {
|
|
930
|
+
self.type = window.innerWidth > 640 ? self.type = 'default' : (self.autocomplete ? 'searchbar' : 'picker');
|
|
931
|
+
}
|
|
932
|
+
// Track
|
|
933
|
+
changesDetected = false;
|
|
934
|
+
// Open the modal
|
|
935
|
+
self.modal.open();
|
|
936
|
+
}
|
|
676
937
|
}
|
|
677
938
|
}
|
|
678
939
|
|
|
679
|
-
self.
|
|
940
|
+
self.close = function (options) {
|
|
680
941
|
if (self.modal) {
|
|
681
|
-
if (
|
|
682
|
-
self.
|
|
942
|
+
if (options?.origin) {
|
|
943
|
+
self.modal.close(options)
|
|
683
944
|
} else {
|
|
684
|
-
self.close()
|
|
945
|
+
self.modal.close({ origin: 'button' })
|
|
685
946
|
}
|
|
686
947
|
}
|
|
687
948
|
}
|
|
688
949
|
|
|
689
|
-
self.
|
|
690
|
-
if (self.
|
|
691
|
-
|
|
692
|
-
if (e.changedTouches && e.changedTouches[0]) {
|
|
693
|
-
x = e.changedTouches[0].clientX;
|
|
694
|
-
} else {
|
|
695
|
-
x = e.clientX;
|
|
696
|
-
}
|
|
697
|
-
if (e.target.offsetWidth - (x - e.target.offsetLeft) < 20) {
|
|
698
|
-
self.toggle();
|
|
699
|
-
} else {
|
|
700
|
-
self.open();
|
|
701
|
-
}
|
|
702
|
-
} else {
|
|
703
|
-
self.toggle();
|
|
950
|
+
self.isClosed = function() {
|
|
951
|
+
if (self.modal) {
|
|
952
|
+
return self.modal.isClosed();
|
|
704
953
|
}
|
|
705
954
|
}
|
|
706
955
|
|
|
707
|
-
self.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
if (s.selected) {
|
|
732
|
-
value = [s];
|
|
733
|
-
} else {
|
|
734
|
-
value = [];
|
|
735
|
-
}
|
|
736
|
-
// Close the modal
|
|
737
|
-
self.close();
|
|
738
|
-
}
|
|
956
|
+
self.setData = function(data) {
|
|
957
|
+
self.data = data;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
self.getData = function() {
|
|
961
|
+
return self.data;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
self.getValue = function() {
|
|
965
|
+
return self.value;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
self.setValue = function(v) {
|
|
969
|
+
self.value = v;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
self.reset = function() {
|
|
973
|
+
self.value = null;
|
|
974
|
+
self.close({ origin: 'button' });
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
self.onevent = function(e) {
|
|
978
|
+
if (events[e.type]) {
|
|
979
|
+
events[e.type](e);
|
|
739
980
|
}
|
|
740
981
|
}
|
|
741
982
|
|
|
742
|
-
|
|
743
|
-
|
|
983
|
+
// Init with a
|
|
984
|
+
let input = self.input;
|
|
985
|
+
|
|
986
|
+
onload(() => {
|
|
987
|
+
if (self.type === "inline") {
|
|
988
|
+
// For inline dropdown
|
|
989
|
+
self.el.setAttribute('tabindex', 0);
|
|
990
|
+
// Remove search
|
|
991
|
+
self.input.remove();
|
|
992
|
+
} else {
|
|
744
993
|
// Create modal instance
|
|
745
994
|
self.modal = {
|
|
746
995
|
closed: true,
|
|
747
996
|
focus: false,
|
|
748
|
-
width: self.width,
|
|
749
997
|
onopen: onopen,
|
|
750
998
|
onclose: onclose,
|
|
751
999
|
position: 'absolute',
|
|
@@ -754,74 +1002,50 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
754
1002
|
};
|
|
755
1003
|
// Generate modal
|
|
756
1004
|
Modal(self.el.children[1], self.modal);
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
// Autocomplete will be forced to be true when insert action is active
|
|
1008
|
+
if ((self.insert || self.type === 'searchbar') && ! self.autocomplete) {
|
|
1009
|
+
self.autocomplete = true;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
if (typeof(input) !== 'undefined') {
|
|
1013
|
+
// Remove the native element
|
|
1014
|
+
if (isDOM(input)) {
|
|
1015
|
+
input.classList.add('lm-dropdown-input');
|
|
1016
|
+
}
|
|
760
1017
|
// Remove search
|
|
761
1018
|
self.input.remove();
|
|
1019
|
+
// New input
|
|
1020
|
+
self.input = input;
|
|
762
1021
|
}
|
|
763
1022
|
|
|
764
1023
|
// Default width
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
1024
|
+
if (self.width) {
|
|
1025
|
+
// Dropdown
|
|
1026
|
+
self.el.style.width = self.width + 'px';
|
|
1027
|
+
}
|
|
768
1028
|
|
|
769
|
-
//
|
|
770
|
-
self.
|
|
771
|
-
if (self.modal) {
|
|
772
|
-
if (!(e.relatedTarget && self.el.contains(e.relatedTarget)) && !self.el.contains(e.relatedTarget)) {
|
|
773
|
-
if (!self.modal.closed) {
|
|
774
|
-
self.modal.closed = true;
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
});
|
|
1029
|
+
// Height
|
|
1030
|
+
self.height = 400;
|
|
779
1031
|
|
|
780
|
-
//
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if (e.key === 'ArrowUp') {
|
|
785
|
-
moveCursor(-1);
|
|
786
|
-
prevent = true;
|
|
787
|
-
} else if (e.key === 'ArrowDown') {
|
|
788
|
-
moveCursor(1);
|
|
789
|
-
prevent = true;
|
|
790
|
-
} else if (e.key === 'Home') {
|
|
791
|
-
moveCursor(-1, true);
|
|
792
|
-
if (!self.autocomplete) {
|
|
793
|
-
prevent = true;
|
|
794
|
-
}
|
|
795
|
-
} else if (e.key === 'End') {
|
|
796
|
-
moveCursor(1, true);
|
|
797
|
-
if (!self.autocomplete) {
|
|
798
|
-
prevent = true;
|
|
799
|
-
}
|
|
800
|
-
} else if (e.key === 'Enter') {
|
|
801
|
-
self.select(e, self.rows[cursor]);
|
|
802
|
-
prevent = true;
|
|
803
|
-
} else if (e.key === 'Escape') {
|
|
804
|
-
self.modal.closed = true;
|
|
805
|
-
prevent = true;
|
|
806
|
-
} else {
|
|
807
|
-
if (e.keyCode === 32 && !self.autocomplete) {
|
|
808
|
-
self.select(e, self.rows[cursor]);
|
|
809
|
-
}
|
|
810
|
-
}
|
|
1032
|
+
// Animation for mobile
|
|
1033
|
+
if (document.documentElement.clientWidth < 800) {
|
|
1034
|
+
self.animation = true;
|
|
1035
|
+
}
|
|
811
1036
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
self.modal.closed = false;
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
});
|
|
1037
|
+
// Events
|
|
1038
|
+
self.el.addEventListener('focusout', events.focusout);
|
|
1039
|
+
self.el.addEventListener('keydown', events.keydown);
|
|
1040
|
+
self.el.addEventListener('mousedown', events.mousedown);
|
|
1041
|
+
self.el.addEventListener('paste', events.paste);
|
|
1042
|
+
self.el.addEventListener('input', events.input);
|
|
822
1043
|
|
|
823
1044
|
// Load remote data
|
|
824
1045
|
if (self.url) {
|
|
1046
|
+
// Loading spin
|
|
1047
|
+
self.el.classList.add('lm-dropdown-loading');
|
|
1048
|
+
// Load remote data
|
|
825
1049
|
fetch(self.url, {
|
|
826
1050
|
headers: {
|
|
827
1051
|
'Content-Type': 'text/json',
|
|
@@ -830,9 +1054,9 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
830
1054
|
} else {
|
|
831
1055
|
loadData();
|
|
832
1056
|
}
|
|
833
|
-
}
|
|
1057
|
+
});
|
|
834
1058
|
|
|
835
|
-
|
|
1059
|
+
onchange(prop => {
|
|
836
1060
|
if (prop === 'value') {
|
|
837
1061
|
setValue(self.value);
|
|
838
1062
|
} else if (prop === 'data') {
|
|
@@ -843,36 +1067,21 @@ if (!Modal && typeof (require) === 'function') {
|
|
|
843
1067
|
if (typeof (lazyloading) === 'function') {
|
|
844
1068
|
lazyloading(prop);
|
|
845
1069
|
}
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
/**
|
|
849
|
-
* Sanitize any HTML from be paste on the search
|
|
850
|
-
* @param e
|
|
851
|
-
*/
|
|
852
|
-
self.onpaste = function (e) {
|
|
853
|
-
let text;
|
|
854
|
-
if (e.clipboardData || e.originalEvent.clipboardData) {
|
|
855
|
-
text = (e.originalEvent || e).clipboardData.getData('text/plain');
|
|
856
|
-
} else if (window.clipboardData) {
|
|
857
|
-
text = window.clipboardData.getData('Text');
|
|
858
|
-
}
|
|
859
|
-
text = text.replace(/(\r\n|\n|\r)/gm, "");
|
|
860
|
-
document.execCommand('insertText', false, text)
|
|
861
|
-
e.preventDefault();
|
|
862
|
-
}
|
|
1070
|
+
});
|
|
863
1071
|
|
|
864
|
-
return `<div class="lm-dropdown" data-
|
|
1072
|
+
return render => render`<div class="lm-dropdown" data-state="{{self.state}}" data-insert="{{self.insert}}" data-type="{{self.type}}" :value="self.value" :data="self.data">
|
|
865
1073
|
<div class="lm-dropdown-header">
|
|
866
|
-
<div class="lm-dropdown-input"
|
|
867
|
-
<
|
|
1074
|
+
<div class="lm-dropdown-input" placeholder="{{self.placeholder}}" :ref="self.input" tabindex="0"></div>
|
|
1075
|
+
<button class="lm-dropdown-add" onclick="${add}" tabindex="0"></button>
|
|
868
1076
|
<div class="lm-dropdown-header-controls">
|
|
869
|
-
<button onclick="self.
|
|
1077
|
+
<button onclick="self.reset" class="lm-dropdown-done">${T('Reset')}</button>
|
|
1078
|
+
<button onclick="self.close" class="lm-dropdown-done">${T('Done')}</button>
|
|
870
1079
|
</div>
|
|
871
1080
|
</div>
|
|
872
1081
|
<div class="lm-dropdown-content">
|
|
873
1082
|
<div>
|
|
874
1083
|
<div :loop="self.result" :ref="self.container" :rows="self.rows">
|
|
875
|
-
<div class="lm-dropdown-item" onclick="
|
|
1084
|
+
<div class="lm-dropdown-item" onclick="${select}" data-cursor="{{self.cursor}}" data-selected="{{self.selected}}" data-group="{{self.header}}">
|
|
876
1085
|
<div><img :src="self.image" /> <div>{{self.text}}</div></div>
|
|
877
1086
|
</div>
|
|
878
1087
|
</div>
|
package/dist/style.css
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
.lm-dropdown {
|
|
2
|
-
display: inline-block;
|
|
3
2
|
user-select: none;
|
|
4
3
|
cursor: pointer;
|
|
5
4
|
box-sizing: border-box;
|
|
6
5
|
outline-offset: 1px;
|
|
6
|
+
vertical-align: top;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.lm-dropdown-header {
|
|
@@ -23,18 +23,19 @@
|
|
|
23
23
|
cursor: pointer;
|
|
24
24
|
padding: 15px;
|
|
25
25
|
font-weight: bold;
|
|
26
|
-
outline: 0;
|
|
27
26
|
border: 0;
|
|
28
27
|
color: var(--lm-main-color);
|
|
28
|
+
margin: 1px;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
.lm-dropdown-content {
|
|
32
32
|
position: relative;
|
|
33
|
+
margin-top: 1px;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
.lm-dropdown .lm-modal {
|
|
36
37
|
padding: 0;
|
|
37
|
-
min-width:
|
|
38
|
+
min-width: 100%;
|
|
38
39
|
min-height: 5px;
|
|
39
40
|
border: 1px solid var(--lm-border-color, #ccc);
|
|
40
41
|
border-radius: 0;
|
|
@@ -50,9 +51,17 @@
|
|
|
50
51
|
box-sizing: border-box;
|
|
51
52
|
width: 100%;
|
|
52
53
|
background: var(--lm-background-color, #fff);
|
|
53
|
-
border: 1px solid var(--lm-border-color, #
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
border: 1px solid var(--lm-border-color, #767676);
|
|
55
|
+
border-radius: var(--lm-border-radius, 2px);
|
|
56
|
+
position: relative;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media (prefers-color-scheme: dark) {
|
|
60
|
+
.lm-dropdown-input {
|
|
61
|
+
background: var(--lm-background-color, #3b3b3b);
|
|
62
|
+
border: 1px solid var(--lm-border-color, #858585);
|
|
63
|
+
color: var(--lm-text-color, #fff);
|
|
64
|
+
}
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
.lm-dropdown-input > br {
|
|
@@ -77,11 +86,16 @@
|
|
|
77
86
|
transition: transform .1s ease-in-out;
|
|
78
87
|
}
|
|
79
88
|
|
|
89
|
+
.lm-application .lm-dropdown-add,
|
|
80
90
|
.lm-dropdown-add {
|
|
81
91
|
position: absolute;
|
|
82
|
-
padding:
|
|
83
|
-
right:
|
|
92
|
+
padding: 6px 6px;
|
|
93
|
+
right: 30px;
|
|
84
94
|
display: none;
|
|
95
|
+
margin: 0;
|
|
96
|
+
border: 0;
|
|
97
|
+
background: transparent;
|
|
98
|
+
cursor: pointer;
|
|
85
99
|
}
|
|
86
100
|
|
|
87
101
|
.lm-dropdown-add::after {
|
|
@@ -136,7 +150,7 @@
|
|
|
136
150
|
color: #000;
|
|
137
151
|
display: flex;
|
|
138
152
|
align-items: center;
|
|
139
|
-
padding: 4px 40px 4px
|
|
153
|
+
padding: 4px 40px 4px 10px;
|
|
140
154
|
position: relative;
|
|
141
155
|
box-sizing: border-box;
|
|
142
156
|
}
|
|
@@ -208,7 +222,7 @@
|
|
|
208
222
|
border-top: 1px solid var(--lm-border-color);
|
|
209
223
|
border-bottom: 1px solid var(--lm-border-color);
|
|
210
224
|
box-shadow: 0 0 12px rgb(0 0 0 / 22%);
|
|
211
|
-
justify-content:
|
|
225
|
+
justify-content: space-between;
|
|
212
226
|
}
|
|
213
227
|
|
|
214
228
|
.lm-dropdown[data-type="picker"] .lm-modal {
|
|
@@ -219,6 +233,10 @@
|
|
|
219
233
|
height: 300px !important;
|
|
220
234
|
}
|
|
221
235
|
|
|
236
|
+
.lm-dropdown[data-type="picker"] .lm-lazy {
|
|
237
|
+
width: 100% !important;
|
|
238
|
+
}
|
|
239
|
+
|
|
222
240
|
.lm-dropdown[data-type="picker"] .lm-dropdown-item > div {
|
|
223
241
|
border-bottom: solid 1px rgba(0, 0, 0, 0.2);
|
|
224
242
|
text-transform: uppercase;
|
|
@@ -257,17 +275,16 @@
|
|
|
257
275
|
position: initial;
|
|
258
276
|
}
|
|
259
277
|
|
|
260
|
-
.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-header
|
|
261
|
-
display:
|
|
262
|
-
position: fixed;
|
|
263
|
-
right: 0;
|
|
264
|
-
top: 0;
|
|
278
|
+
.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-header {
|
|
279
|
+
display: flex;
|
|
265
280
|
background-color: #fff;
|
|
266
|
-
z-index: 1;
|
|
267
|
-
padding-top: 5px;
|
|
268
281
|
box-sizing: border-box;
|
|
269
282
|
}
|
|
270
283
|
|
|
284
|
+
.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-header-controls {
|
|
285
|
+
display: flex;
|
|
286
|
+
}
|
|
287
|
+
|
|
271
288
|
.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-input {
|
|
272
289
|
font-size: 1.5em;
|
|
273
290
|
border-radius: 0;
|
|
@@ -279,6 +296,7 @@
|
|
|
279
296
|
padding-bottom: 0;
|
|
280
297
|
line-height: 60px;
|
|
281
298
|
height: 60px;
|
|
299
|
+
flex: 1;
|
|
282
300
|
}
|
|
283
301
|
|
|
284
302
|
.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-input::after {
|
|
@@ -286,7 +304,15 @@
|
|
|
286
304
|
}
|
|
287
305
|
|
|
288
306
|
.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-add {
|
|
289
|
-
right:
|
|
307
|
+
right: 150px;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.lm-dropdown[data-type="searchbar"][data-state="true"]:not(.lm-dropdown-loading) .lm-dropdown-add::after {
|
|
311
|
+
content: 'add';
|
|
312
|
+
font-family: "Material Symbols Outlined", "Material Icons";
|
|
313
|
+
font-size: 24px;
|
|
314
|
+
width: 24px;
|
|
315
|
+
height: 24px;
|
|
290
316
|
}
|
|
291
317
|
|
|
292
318
|
.lm-dropdown[data-type="searchbar"] .lm-modal {
|
|
@@ -312,12 +338,16 @@
|
|
|
312
338
|
|
|
313
339
|
.lm-dropdown[data-type="searchbar"] .lm-lazy {
|
|
314
340
|
max-height: initial;
|
|
341
|
+
width: 100% !important;
|
|
315
342
|
}
|
|
316
343
|
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
|
|
317
348
|
.lm-dropdown .lm-lazy {
|
|
318
349
|
max-height: 300px;
|
|
319
350
|
scrollbar-width: thin;
|
|
320
|
-
padding-bottom: 5px;
|
|
321
351
|
}
|
|
322
352
|
|
|
323
353
|
.lm-dropdown .lm-lazy::-webkit-scrollbar {
|
|
@@ -328,9 +358,9 @@
|
|
|
328
358
|
width: 12px;
|
|
329
359
|
}
|
|
330
360
|
|
|
331
|
-
.lm-dropdown-loading .lm-dropdown-add::after {
|
|
332
|
-
content: '';
|
|
361
|
+
.lm-dropdown.lm-dropdown-loading .lm-dropdown-add::after {
|
|
333
362
|
position: absolute;
|
|
363
|
+
content: '';
|
|
334
364
|
width: 12px;
|
|
335
365
|
height: 12px;
|
|
336
366
|
margin-top: -7px;
|
package/package.json
CHANGED
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"javascript plugins"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"lemonadejs": "^
|
|
18
|
-
"@lemonadejs/modal": "^
|
|
17
|
+
"lemonadejs": "^5.2.0",
|
|
18
|
+
"@lemonadejs/modal": "^5.2.0"
|
|
19
19
|
},
|
|
20
20
|
"main": "dist/index.js",
|
|
21
21
|
"types": "dist/index.d.ts",
|
|
22
|
-
"version": "
|
|
22
|
+
"version": "5.2.0"
|
|
23
23
|
}
|