selectic 1.3.11 → 3.0.3
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 +6 -5
- package/dist/selectic.common.js +708 -594
- package/dist/selectic.esm.js +670 -557
- package/doc/breakingChanges.md +55 -0
- package/doc/events.md +68 -17
- package/doc/main.md +7 -0
- package/doc/params.md +5 -2
- package/package.json +46 -41
- package/src/ExtendedList.tsx +14 -13
- package/src/Filter.tsx +34 -22
- package/src/List.tsx +14 -13
- package/src/MainInput.tsx +26 -27
- package/src/Store.tsx +446 -291
- package/src/css/selectic.css +6 -0
- package/src/index.tsx +249 -140
- package/test/Selectic/Selectic_props.spec.js +29 -10
- package/test/Store/Store_creation.spec.js +451 -438
- package/test/Store/Store_props.spec.js +119 -159
- package/test/Store/Store_state.spec.js +9 -13
- package/test/Store/changeGroups.spec.js +4 -6
- package/test/Store/changeTexts.spec.js +28 -30
- package/test/Store/clearCache.spec.js +24 -8
- package/test/Store/commit.spec.js +256 -99
- package/test/Store/getItem.spec.js +30 -38
- package/test/Store/getItems.spec.js +33 -43
- package/test/Store/selectItem.spec.js +4 -4
- package/test/Store/toggleSelectAll.spec.js +50 -52
- package/test/helper.js +3 -0
- package/test/tools.js +4 -2
- package/tsconfig.json +5 -0
- package/types/ExtendedList.d.ts +6 -6
- package/types/Filter.d.ts +5 -5
- package/types/List.d.ts +33 -9
- package/types/MainInput.d.ts +5 -5
- package/types/Store.d.ts +176 -42
- package/types/index.d.ts +54 -24
- package/types/OldStore.d.ts +0 -195
package/src/css/selectic.css
CHANGED
|
@@ -220,6 +220,12 @@
|
|
|
220
220
|
opacity: 0;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
+
.selectic-item_text {
|
|
224
|
+
white-space: nowrap;
|
|
225
|
+
text-overflow: ellipsis;
|
|
226
|
+
overflow: hidden;
|
|
227
|
+
}
|
|
228
|
+
|
|
223
229
|
.selectic-item__active {
|
|
224
230
|
background-color: var(--selectic-active-item-bg);
|
|
225
231
|
color: var(--selectic-active-item-color);
|
package/src/index.tsx
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* close [component]: triggered when the list closes.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import {Vue, Component, Prop, Watch} from 'vtyx';
|
|
21
|
+
import {Vue, Component, Prop, Watch, h} from 'vtyx';
|
|
22
22
|
import './css/selectic.css';
|
|
23
23
|
|
|
24
24
|
import Store, {
|
|
@@ -36,6 +36,7 @@ import Store, {
|
|
|
36
36
|
FormatCallback,
|
|
37
37
|
SelectionOverflow,
|
|
38
38
|
ListPosition,
|
|
39
|
+
HideFilter,
|
|
39
40
|
} from './Store';
|
|
40
41
|
import MainInput from './MainInput';
|
|
41
42
|
import ExtendedList from './ExtendedList';
|
|
@@ -55,8 +56,21 @@ export {
|
|
|
55
56
|
FormatCallback,
|
|
56
57
|
SelectionOverflow,
|
|
57
58
|
ListPosition,
|
|
59
|
+
HideFilter,
|
|
58
60
|
};
|
|
59
61
|
|
|
62
|
+
type EventType = 'input' | 'change' | 'open' | 'close' | 'focus' | 'blur' | 'item:click';
|
|
63
|
+
|
|
64
|
+
export interface EventOptions {
|
|
65
|
+
instance: Selectic;
|
|
66
|
+
eventType: EventType;
|
|
67
|
+
automatic: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface EventChangeOptions extends EventOptions {
|
|
71
|
+
isExcluded: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
60
74
|
export interface ParamProps {
|
|
61
75
|
/* Method to call to fetch extra data */
|
|
62
76
|
fetchCallback?: FetchCallback;
|
|
@@ -71,7 +85,7 @@ export interface ParamProps {
|
|
|
71
85
|
pageSize?: number;
|
|
72
86
|
|
|
73
87
|
/* Hide the search control */
|
|
74
|
-
hideFilter?:
|
|
88
|
+
hideFilter?: HideFilter;
|
|
75
89
|
|
|
76
90
|
/* Allow to reverse selection.
|
|
77
91
|
* If true, parent should support the selectionIsExcluded property.
|
|
@@ -126,6 +140,17 @@ export interface ParamProps {
|
|
|
126
140
|
keepOpenWithOtherSelectic?: boolean;
|
|
127
141
|
}
|
|
128
142
|
|
|
143
|
+
export type OnCallback = (event: string, ...args: any[]) => void;
|
|
144
|
+
export type GetMethodsCallback = (methods: {
|
|
145
|
+
clearCache: Selectic['clearCache'];
|
|
146
|
+
changeTexts: Selectic['changeTexts'];
|
|
147
|
+
getValue: Selectic['getValue'];
|
|
148
|
+
getSelectedItems: Selectic['getSelectedItems'];
|
|
149
|
+
isEmpty: Selectic['isEmpty'];
|
|
150
|
+
toggleOpen: Selectic['toggleOpen'];
|
|
151
|
+
}) => void;
|
|
152
|
+
|
|
153
|
+
|
|
129
154
|
export interface Props {
|
|
130
155
|
/* Selectic's initial value */
|
|
131
156
|
value?: SelectedValue;
|
|
@@ -173,6 +198,17 @@ export interface Props {
|
|
|
173
198
|
* attributes of select.
|
|
174
199
|
*/
|
|
175
200
|
params?: ParamProps;
|
|
201
|
+
|
|
202
|
+
/** _on is used mainly for tests.
|
|
203
|
+
* Its purpose is to propagate $emit event mainly
|
|
204
|
+
* for parents which are not in Vue environment.
|
|
205
|
+
*/
|
|
206
|
+
_on?: OnCallback;
|
|
207
|
+
|
|
208
|
+
/** _getMethods is used mainly for tests.
|
|
209
|
+
* Its purpose is to provide public methods outside of a Vue environment.
|
|
210
|
+
*/
|
|
211
|
+
_getMethods?: GetMethodsCallback;
|
|
176
212
|
}
|
|
177
213
|
|
|
178
214
|
export function changeTexts(texts: PartialMessages) {
|
|
@@ -234,6 +270,13 @@ export default class Selectic extends Vue<Props> {
|
|
|
234
270
|
})})
|
|
235
271
|
public params: ParamProps;
|
|
236
272
|
|
|
273
|
+
/** For tests */
|
|
274
|
+
@Prop()
|
|
275
|
+
public _on?: OnCallback;
|
|
276
|
+
|
|
277
|
+
@Prop()
|
|
278
|
+
public _getMethods?: GetMethodsCallback;
|
|
279
|
+
|
|
237
280
|
/* }}} */
|
|
238
281
|
/* {{{ data */
|
|
239
282
|
|
|
@@ -242,6 +285,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
242
285
|
public elementLeft = 0;
|
|
243
286
|
public elementRight = 0;
|
|
244
287
|
public width = 0;
|
|
288
|
+
private hasBeenRendered = false;
|
|
245
289
|
|
|
246
290
|
private store: Store = {} as Store;
|
|
247
291
|
|
|
@@ -253,10 +297,10 @@ export default class Selectic extends Vue<Props> {
|
|
|
253
297
|
/* {{{ computed */
|
|
254
298
|
|
|
255
299
|
get isFocused() {
|
|
256
|
-
if (!this.
|
|
300
|
+
if (!this.hasBeenRendered) {
|
|
257
301
|
return false;
|
|
258
302
|
}
|
|
259
|
-
return this.store.state.isOpen;
|
|
303
|
+
return !!this.store.state.isOpen;
|
|
260
304
|
}
|
|
261
305
|
|
|
262
306
|
get scrollListener() {
|
|
@@ -393,17 +437,18 @@ export default class Selectic extends Vue<Props> {
|
|
|
393
437
|
private computeOffset(doNotAddListener = false) {
|
|
394
438
|
const mainInput = this.$refs.mainInput;
|
|
395
439
|
|
|
396
|
-
|
|
440
|
+
const mainEl = mainInput?.$el as HTMLElement;
|
|
441
|
+
|
|
442
|
+
if (!mainEl) {
|
|
397
443
|
/* This method has been called too soon (before render function) */
|
|
398
444
|
return;
|
|
399
445
|
}
|
|
400
446
|
|
|
401
|
-
const mainEl = mainInput.$el as HTMLElement;
|
|
402
447
|
const _elementsListeners = this._elementsListeners;
|
|
403
448
|
|
|
404
449
|
/* add listeners */
|
|
405
450
|
if (!doNotAddListener) {
|
|
406
|
-
let el =
|
|
451
|
+
let el = mainEl;
|
|
407
452
|
while (el) {
|
|
408
453
|
el.addEventListener('scroll', this.scrollListener, { passive: true });
|
|
409
454
|
_elementsListeners.push(el);
|
|
@@ -452,14 +497,14 @@ export default class Selectic extends Vue<Props> {
|
|
|
452
497
|
window.addEventListener('resize', this.windowResize, false);
|
|
453
498
|
document.addEventListener('click', this.outsideListener, true);
|
|
454
499
|
this.computeOffset();
|
|
455
|
-
this
|
|
500
|
+
this.emit('open');
|
|
456
501
|
} else {
|
|
457
502
|
this.removeListeners();
|
|
458
503
|
if (state.status.hasChanged) {
|
|
459
504
|
this.$emit('change', this.getValue(), state.selectionIsExcluded, this);
|
|
460
505
|
this.store.resetChange();
|
|
461
506
|
}
|
|
462
|
-
this
|
|
507
|
+
this.emit('close');
|
|
463
508
|
}
|
|
464
509
|
}
|
|
465
510
|
|
|
@@ -480,7 +525,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
480
525
|
/* {{{ watch */
|
|
481
526
|
|
|
482
527
|
@Watch('value')
|
|
483
|
-
|
|
528
|
+
public onValueChange() {
|
|
484
529
|
const currentValue = this.store.state.internalValue;
|
|
485
530
|
const newValue = this.value ?? null;
|
|
486
531
|
const areSimilar = this.compareValues(
|
|
@@ -494,17 +539,17 @@ export default class Selectic extends Vue<Props> {
|
|
|
494
539
|
}
|
|
495
540
|
|
|
496
541
|
@Watch('selectionIsExcluded')
|
|
497
|
-
|
|
498
|
-
this.store.selectionIsExcluded = this.selectionIsExcluded;
|
|
542
|
+
public onExcludedChange() {
|
|
543
|
+
this.store.props.selectionIsExcluded = this.selectionIsExcluded;
|
|
499
544
|
}
|
|
500
545
|
|
|
501
546
|
@Watch('options')
|
|
502
|
-
|
|
503
|
-
this.store.options = this.options;
|
|
547
|
+
public onOptionsChange() {
|
|
548
|
+
this.store.props.options = Array.from(this.options);
|
|
504
549
|
}
|
|
505
550
|
|
|
506
551
|
@Watch('texts')
|
|
507
|
-
|
|
552
|
+
public onTextsChange() {
|
|
508
553
|
const texts = this.texts;
|
|
509
554
|
|
|
510
555
|
if (texts) {
|
|
@@ -513,45 +558,46 @@ export default class Selectic extends Vue<Props> {
|
|
|
513
558
|
}
|
|
514
559
|
|
|
515
560
|
@Watch('disabled')
|
|
516
|
-
|
|
517
|
-
this.store.disabled = this.disabled;
|
|
561
|
+
public onDisabledChange() {
|
|
562
|
+
this.store.props.disabled = this.disabled;
|
|
518
563
|
}
|
|
519
564
|
|
|
520
565
|
@Watch('groups')
|
|
521
|
-
|
|
566
|
+
public onGroupsChanged() {
|
|
522
567
|
this.store.changeGroups(this.groups);
|
|
523
568
|
}
|
|
524
569
|
|
|
525
570
|
@Watch('placeholder')
|
|
526
|
-
|
|
571
|
+
public onPlaceholderChanged() {
|
|
527
572
|
this.store.commit('placeholder', this.placeholder);
|
|
528
573
|
}
|
|
529
574
|
|
|
530
575
|
@Watch('open')
|
|
531
|
-
|
|
576
|
+
public onOpenChanged() {
|
|
532
577
|
this.store.commit('isOpen', this.open ?? false);
|
|
533
578
|
}
|
|
534
579
|
|
|
535
580
|
@Watch('isFocused')
|
|
536
|
-
|
|
581
|
+
public onFocusChanged() {
|
|
537
582
|
this.focusToggled();
|
|
538
583
|
}
|
|
539
584
|
|
|
540
585
|
@Watch('store.state.internalValue')
|
|
541
|
-
|
|
586
|
+
public onInternalValueChange() {
|
|
542
587
|
const oldValue = this._oldValue;
|
|
543
588
|
const value = this.getValue();
|
|
544
589
|
const areSimilar = this.compareValues(oldValue, value);
|
|
545
|
-
/* should not trigger when initializing internalValue, but should do
|
|
590
|
+
/* should not trigger when initializing internalValue, but should do
|
|
591
|
+
* if it changes the initial value */
|
|
546
592
|
const canTrigger = (oldValue !== undefined || !this.hasGivenValue) && !areSimilar;
|
|
547
593
|
|
|
548
594
|
if (canTrigger) {
|
|
549
595
|
const selectionIsExcluded = this.store.state.selectionIsExcluded;
|
|
550
596
|
|
|
551
|
-
this
|
|
597
|
+
this.emit('input', value, selectionIsExcluded);
|
|
552
598
|
|
|
553
599
|
if (!this.isFocused) {
|
|
554
|
-
this
|
|
600
|
+
this.emit('change', value, selectionIsExcluded);
|
|
555
601
|
this.store.resetChange();
|
|
556
602
|
}
|
|
557
603
|
}
|
|
@@ -581,99 +627,145 @@ export default class Selectic extends Vue<Props> {
|
|
|
581
627
|
}, 0);
|
|
582
628
|
}
|
|
583
629
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
for (const [key, value] of Object.entries(staticStyle)) {
|
|
591
|
-
styles.push(`${key}: ${value}`);
|
|
592
|
-
}
|
|
593
|
-
return styles.join(';');
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
const domProps = node.data?.domProps;
|
|
597
|
-
const attrs = node.data?.attrs;
|
|
598
|
-
const id = domProps?.value ?? attrs?.value ?? attrs?.id ?? text;
|
|
599
|
-
const className = node.data?.staticClass;
|
|
600
|
-
const style = styleToString(node.data?.staticStyle);
|
|
601
|
-
|
|
602
|
-
const optVal: OptionValue = {
|
|
603
|
-
id,
|
|
604
|
-
text,
|
|
605
|
-
className,
|
|
606
|
-
style,
|
|
607
|
-
};
|
|
630
|
+
/* This method is only to emit the events and to replicate them */
|
|
631
|
+
private _emit(event: 'input' | 'change', value: SelectedValue, options: EventChangeOptions): void;
|
|
632
|
+
private _emit(event: 'open' | 'close' | 'focus' | 'blur', options: EventOptions): void;
|
|
633
|
+
private _emit(event: 'item:click', value: OptionId, options: EventOptions): void;
|
|
634
|
+
private _emit(event: EventType, ...args: any[]) {
|
|
635
|
+
this.$emit(event, ...args);
|
|
608
636
|
|
|
609
|
-
if (
|
|
610
|
-
|
|
611
|
-
switch(key) {
|
|
612
|
-
case 'title':
|
|
613
|
-
optVal.title = val;
|
|
614
|
-
break;
|
|
615
|
-
case 'disabled':
|
|
616
|
-
if (val === false) {
|
|
617
|
-
optVal.disabled = false;
|
|
618
|
-
} else {
|
|
619
|
-
optVal.disabled = true;
|
|
620
|
-
}
|
|
621
|
-
break;
|
|
622
|
-
case 'group':
|
|
623
|
-
optVal.group = val;
|
|
624
|
-
break;
|
|
625
|
-
case 'icon':
|
|
626
|
-
optVal.icon = val;
|
|
627
|
-
break;
|
|
628
|
-
case 'data':
|
|
629
|
-
optVal.data = val;
|
|
630
|
-
break;
|
|
631
|
-
default:
|
|
632
|
-
if (key.startsWith('data')) {
|
|
633
|
-
if (typeof optVal.data !== 'object') {
|
|
634
|
-
optVal.data = {};
|
|
635
|
-
}
|
|
636
|
-
optVal.data[key.slice(5)] = val;
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
}
|
|
637
|
+
if (typeof this._on === 'function') {
|
|
638
|
+
this._on(event, ...args);
|
|
640
639
|
}
|
|
641
|
-
|
|
642
|
-
return optVal;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
private extractOptionFromNode(node: Vue.VNode): OptionValue {
|
|
646
|
-
const children = node.children;
|
|
647
|
-
const text = (children && children[0].text || '').trim();
|
|
648
|
-
|
|
649
|
-
return this.extractFromNode(node, text);
|
|
650
640
|
}
|
|
651
641
|
|
|
652
|
-
private
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
const
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
642
|
+
private emit(event: 'input' | 'change', value: SelectedValue, isExcluded: boolean): void;
|
|
643
|
+
private emit(event: 'open' | 'close' | 'focus' | 'blur'): void;
|
|
644
|
+
private emit(event: 'item:click', value: OptionId): void;
|
|
645
|
+
private emit(event: EventType, value?: SelectedValue | OptionId, isExcluded?: boolean) {
|
|
646
|
+
const automatic = this.store.state.status.automaticChange;
|
|
647
|
+
const options: EventOptions = {
|
|
648
|
+
instance: this,
|
|
649
|
+
eventType: event,
|
|
650
|
+
automatic,
|
|
651
|
+
};
|
|
652
|
+
switch (event) {
|
|
653
|
+
case 'input':
|
|
654
|
+
case 'change':
|
|
655
|
+
const changeOptions: EventChangeOptions = Object.assign({
|
|
656
|
+
isExcluded: isExcluded!,
|
|
657
|
+
}, options);
|
|
658
|
+
this._emit(event, value as SelectedValue, changeOptions);
|
|
659
|
+
break;
|
|
660
|
+
case 'open':
|
|
661
|
+
case 'focus':
|
|
662
|
+
this._emit('open', options);
|
|
663
|
+
this._emit('focus', options);
|
|
664
|
+
break;
|
|
665
|
+
case 'close':
|
|
666
|
+
case 'blur':
|
|
667
|
+
this._emit('close', options);
|
|
668
|
+
this._emit('blur', options);
|
|
669
|
+
break;
|
|
670
|
+
case 'item:click':
|
|
671
|
+
this._emit(event, value as OptionId, options);
|
|
672
|
+
break;
|
|
662
673
|
}
|
|
663
|
-
|
|
664
|
-
const opt = this.extractFromNode(node, text);
|
|
665
|
-
opt.options = options;
|
|
666
|
-
|
|
667
|
-
return opt;
|
|
668
674
|
}
|
|
669
675
|
|
|
676
|
+
// private extractFromNode(node: Vue.VNode, text = ''): OptionValue {
|
|
677
|
+
// function styleToString(staticStyle?: {[key: string]: string}): string | undefined {
|
|
678
|
+
// if (!staticStyle) {
|
|
679
|
+
// return;
|
|
680
|
+
// }
|
|
681
|
+
// let styles = [];
|
|
682
|
+
// for (const [key, value] of Object.entries(staticStyle)) {
|
|
683
|
+
// styles.push(`${key}: ${value}`);
|
|
684
|
+
// }
|
|
685
|
+
// return styles.join(';');
|
|
686
|
+
// }
|
|
687
|
+
|
|
688
|
+
// const domProps = node.data?.domProps;
|
|
689
|
+
// const attrs = node.data?.attrs;
|
|
690
|
+
// const id = domProps?.value ?? attrs?.value ?? attrs?.id ?? text;
|
|
691
|
+
// const className = node.data?.staticClass;
|
|
692
|
+
// const style = styleToString(node.data?.staticStyle);
|
|
693
|
+
|
|
694
|
+
// const optVal: OptionValue = {
|
|
695
|
+
// id,
|
|
696
|
+
// text,
|
|
697
|
+
// className,
|
|
698
|
+
// style,
|
|
699
|
+
// };
|
|
700
|
+
|
|
701
|
+
// if (attrs) {
|
|
702
|
+
// for (const [key, val] of Object.entries(attrs)) {
|
|
703
|
+
// switch(key) {
|
|
704
|
+
// case 'title':
|
|
705
|
+
// optVal.title = val;
|
|
706
|
+
// break;
|
|
707
|
+
// case 'disabled':
|
|
708
|
+
// if (val === false) {
|
|
709
|
+
// optVal.disabled = false;
|
|
710
|
+
// } else {
|
|
711
|
+
// optVal.disabled = true;
|
|
712
|
+
// }
|
|
713
|
+
// break;
|
|
714
|
+
// case 'group':
|
|
715
|
+
// optVal.group = val;
|
|
716
|
+
// break;
|
|
717
|
+
// case 'icon':
|
|
718
|
+
// optVal.icon = val;
|
|
719
|
+
// break;
|
|
720
|
+
// case 'data':
|
|
721
|
+
// optVal.data = val;
|
|
722
|
+
// break;
|
|
723
|
+
// default:
|
|
724
|
+
// if (key.startsWith('data')) {
|
|
725
|
+
// if (typeof optVal.data !== 'object') {
|
|
726
|
+
// optVal.data = {};
|
|
727
|
+
// }
|
|
728
|
+
// optVal.data[key.slice(5)] = val;
|
|
729
|
+
// }
|
|
730
|
+
// }
|
|
731
|
+
// }
|
|
732
|
+
// }
|
|
733
|
+
|
|
734
|
+
// return optVal;
|
|
735
|
+
// }
|
|
736
|
+
|
|
737
|
+
// private extractOptionFromNode(node: Vue.VNode): OptionValue {
|
|
738
|
+
// const children = node.children;
|
|
739
|
+
// const text = (children && children[0].text || '').trim();
|
|
740
|
+
|
|
741
|
+
// return this.extractFromNode(node, text);
|
|
742
|
+
// }
|
|
743
|
+
|
|
744
|
+
// private extractOptgroupFromNode(node: Vue.VNode): OptionValue {
|
|
745
|
+
// const attrs = node.data?.attrs;
|
|
746
|
+
// const children = node.children || [];
|
|
747
|
+
// const text = attrs?.label || '';
|
|
748
|
+
// const options: OptionValue[] = [];
|
|
749
|
+
|
|
750
|
+
// for (const child of children) {
|
|
751
|
+
// if (child.tag === 'option') {
|
|
752
|
+
// options.push(this.extractOptionFromNode(child));
|
|
753
|
+
// }
|
|
754
|
+
// }
|
|
755
|
+
|
|
756
|
+
// const opt = this.extractFromNode(node, text);
|
|
757
|
+
// opt.options = options;
|
|
758
|
+
|
|
759
|
+
// return opt;
|
|
760
|
+
// }
|
|
761
|
+
|
|
670
762
|
/* }}} */
|
|
671
763
|
/* {{{ Life cycle */
|
|
672
764
|
|
|
673
|
-
|
|
765
|
+
public created() {
|
|
674
766
|
this._elementsListeners = [];
|
|
675
767
|
|
|
676
|
-
this.store = new Store({
|
|
768
|
+
this.store = new Store({
|
|
677
769
|
options: this.options,
|
|
678
770
|
value: this.value,
|
|
679
771
|
selectionIsExcluded: this.selectionIsExcluded,
|
|
@@ -682,10 +774,9 @@ export default class Selectic extends Vue<Props> {
|
|
|
682
774
|
groups: this.groups,
|
|
683
775
|
keepOpenWithOtherSelectic: !!this.params.keepOpenWithOtherSelectic,
|
|
684
776
|
params: {
|
|
685
|
-
multiple: this.multiple,
|
|
777
|
+
multiple: (this.multiple ?? false) !== false,
|
|
686
778
|
pageSize: this.params.pageSize || 100,
|
|
687
|
-
hideFilter: this.params.hideFilter
|
|
688
|
-
? this.params.hideFilter : 'auto',
|
|
779
|
+
hideFilter: this.params.hideFilter ?? 'auto',
|
|
689
780
|
allowRevert: this.params.allowRevert, /* it can be undefined */
|
|
690
781
|
allowClearSelection: this.params.allowClearSelection || false,
|
|
691
782
|
autoSelect: this.params.autoSelect === undefined
|
|
@@ -700,48 +791,66 @@ export default class Selectic extends Vue<Props> {
|
|
|
700
791
|
formatSelection: this.params.formatSelection,
|
|
701
792
|
listPosition: this.params.listPosition || 'auto',
|
|
702
793
|
optionBehavior: this.params.optionBehavior, /* it can be undefined */
|
|
703
|
-
isOpen:
|
|
794
|
+
isOpen: (this.open ?? false) !== false,
|
|
704
795
|
},
|
|
705
796
|
fetchCallback: this.params.fetchCallback,
|
|
706
797
|
getItemsCallback: this.params.getItemsCallback,
|
|
707
|
-
}
|
|
798
|
+
});
|
|
799
|
+
|
|
800
|
+
if (typeof this._getMethods === 'function') {
|
|
801
|
+
this._getMethods({
|
|
802
|
+
clearCache: this.clearCache.bind(this),
|
|
803
|
+
changeTexts: this.changeTexts.bind(this),
|
|
804
|
+
getValue: this.getValue.bind(this),
|
|
805
|
+
getSelectedItems: this.getSelectedItems.bind(this),
|
|
806
|
+
isEmpty: this.isEmpty.bind(this),
|
|
807
|
+
toggleOpen: this.toggleOpen.bind(this),
|
|
808
|
+
});
|
|
809
|
+
}
|
|
708
810
|
}
|
|
709
811
|
|
|
710
|
-
|
|
711
|
-
setTimeout(() =>
|
|
812
|
+
public mounted() {
|
|
813
|
+
setTimeout(() => {
|
|
814
|
+
this.hasBeenRendered = true;
|
|
815
|
+
this.computeOffset();
|
|
816
|
+
}, 100);
|
|
712
817
|
}
|
|
713
818
|
|
|
714
|
-
|
|
715
|
-
const elements = this.$slots.default;
|
|
716
|
-
if (!elements) {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
}
|
|
720
|
-
const options = [];
|
|
721
|
-
|
|
722
|
-
for (const node of elements) {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
}
|
|
819
|
+
public beforeUpdate() {
|
|
820
|
+
// const elements = this.$slots.default;
|
|
821
|
+
// if (!elements) {
|
|
822
|
+
// this.store.childOptions = [];
|
|
823
|
+
// return;
|
|
824
|
+
// }
|
|
825
|
+
// const options = [];
|
|
826
|
+
|
|
827
|
+
// for (const node of elements) {
|
|
828
|
+
// if (node.tag === 'option') {
|
|
829
|
+
// const prop = this.extractOptionFromNode(node);
|
|
830
|
+
// options.push(prop);
|
|
831
|
+
// } else
|
|
832
|
+
// if (node.tag === 'optgroup') {
|
|
833
|
+
// const prop = this.extractOptgroupFromNode(node);
|
|
834
|
+
// options.push(prop);
|
|
835
|
+
// }
|
|
836
|
+
// }
|
|
732
837
|
|
|
733
|
-
this.store.childOptions = options;
|
|
838
|
+
// this.store.childOptions = options;
|
|
734
839
|
}
|
|
735
840
|
|
|
736
|
-
|
|
841
|
+
public beforeDestroy() {
|
|
737
842
|
this.removeListeners();
|
|
738
843
|
}
|
|
739
844
|
|
|
740
845
|
/* }}} */
|
|
741
846
|
|
|
742
|
-
|
|
743
|
-
const h = this.renderWrapper();
|
|
847
|
+
public render() {
|
|
744
848
|
const id = this.id || undefined;
|
|
849
|
+
const store = this.store;
|
|
850
|
+
|
|
851
|
+
if (!store.state) {
|
|
852
|
+
return; /* component is not ready yet */
|
|
853
|
+
}
|
|
745
854
|
|
|
746
855
|
return (
|
|
747
856
|
<div
|
|
@@ -749,7 +858,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
749
858
|
title={this.title}
|
|
750
859
|
data-selectic="true"
|
|
751
860
|
on={{
|
|
752
|
-
'click.prevent.stop': () =>
|
|
861
|
+
'click.prevent.stop': () => store.commit('isOpen', true),
|
|
753
862
|
}}
|
|
754
863
|
>
|
|
755
864
|
{/* This input is for DOM submission */}
|
|
@@ -759,22 +868,22 @@ export default class Selectic extends Vue<Props> {
|
|
|
759
868
|
value={this.inputValue}
|
|
760
869
|
class="selectic__input-value"
|
|
761
870
|
on={{
|
|
762
|
-
focus: () =>
|
|
871
|
+
focus: () => store.commit('isOpen', true),
|
|
763
872
|
blur: this.checkFocus,
|
|
764
873
|
}}
|
|
765
874
|
/>
|
|
766
875
|
<MainInput
|
|
767
|
-
store={
|
|
876
|
+
store={store}
|
|
768
877
|
id={id}
|
|
769
878
|
on={{
|
|
770
|
-
'item:click': (id: OptionId) => this
|
|
879
|
+
'item:click': (id: OptionId) => this.emit('item:click', id),
|
|
771
880
|
}}
|
|
772
881
|
ref="mainInput"
|
|
773
882
|
/>
|
|
774
883
|
{this.isFocused && (
|
|
775
884
|
<ExtendedList
|
|
776
885
|
class={this.className}
|
|
777
|
-
store={
|
|
886
|
+
store={store}
|
|
778
887
|
elementBottom={this.elementBottom}
|
|
779
888
|
elementTop={this.elementTop}
|
|
780
889
|
elementLeft={this.elementLeft}
|