selectic 3.0.14 → 3.0.16
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/selectic.common.js +39 -27
- package/dist/selectic.esm.js +39 -27
- package/doc/list.md +3 -2
- package/package.json +4 -4
- package/src/ExtendedList.tsx +1 -1
- package/src/List.tsx +48 -42
- package/src/Store.tsx +16 -7
- package/src/css/selectic.css +4 -1
- package/src/index.tsx +2 -2
- package/src/tools.ts +1 -0
- package/test/Store/selectItem.spec.js +27 -2
- package/types/List.d.ts +1 -1
- package/types/Store.d.ts +1 -0
- package/types/tools.d.ts +1 -0
package/dist/selectic.common.js
CHANGED
|
@@ -32,12 +32,13 @@ function styleInject(css, ref) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
var css_248z = "/* {{{ Variables */\n\n:root {\n --selectic-font-size: 14px;\n --selectic-cursor-disabled: not-allowed;\n\n /* The main element */\n --selectic-color: #555555;\n --selectic-bg: #ffffff;\n\n /* The main element (when disabled) */\n --selectic-color-disabled: #787878;\n --selectic-bg-disabled: #eeeeee;\n\n /* The list */\n --selectic-panel-bg: #f0f0f0;\n --selectic-separator-bordercolor: #cccccc;\n /* --selectic-item-color: var(--selectic-color); /* Can be set in any CSS configuration */\n\n /* The current selected item */\n --selectic-selected-item-color: #428bca;\n\n /* When mouse is over items or by selecting with key arrows */\n --selectic-active-item-color: #ffffff;\n --selectic-active-item-bg: #66afe9;\n\n /* Selected values in main element */\n --selectic-value-bg: #f0f0f0;\n /* --selectic-more-items-bg: var(--selectic-info-bg); /* can be set in any CSS configuration */\n /* --selectic-more-items-color: var(--selectic-info-color); /* can be set in any CSS configuration */\n --selectic-more-items-bg-disabled: #cccccc;\n\n /* Information message */\n --selectic-info-bg: #5bc0de;\n --selectic-info-color: #ffffff;\n\n /* Error message */\n --selectic-error-bg: #b72c29;\n --selectic-error-color: #ffffff;\n\n /* XXX: Currently it is important to keep this size for a correct scroll\n * height estimation */\n --selectic-input-height: 30px;\n}\n\n/* }}} */\n/* {{{ Bootstrap equivalent style */\n\n.selectic .form-control {\n display: block;\n width: 100%;\n height: calc(var(--selectic-input-height) - 2px);\n font-size: var(--selectic-font-size);\n line-height: 1.42857143;\n color: var(--selectic-color);\n background-color: var(--selectic-bg);\n background-image: none;\n border: 1px solid var(--selectic-separator-bordercolor); /* should use a better variable */\n border-radius: 4px;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n.selectic .has-feedback {\n position: relative;\n}\n.selectic .has-feedback .form-control {\n padding-right: calc(var(--selectic-input-height) + 4px);\n}\n\n.selectic .form-control-feedback.fa,\n.selectic .form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: calc(var(--selectic-input-height) + 4px);\n height: calc(var(--selectic-input-height) + 4px);\n line-height: var(--selectic-input-height);\n text-align: center;\n pointer-events: none;\n}\n\n.selectic .alert-info {\n background-color: var(--selectic-info-bg);\n color: var(--selectic-info-color);\n}\n\n.selectic .alert-danger {\n background-color: var(--selectic-error-bg);\n color: var(--selectic-error-color);\n}\n\n/* }}} */\n\n.selectic * {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.selectic.form-control {\n display: inline-block;\n padding: 0;\n cursor: pointer;\n border: unset;\n}\n\n.has-feedback .selectic__icon-container.form-control-feedback {\n right: 0;\n}\n\n/* The input which contains the selected value\n * XXX: This input should stay hidden behind other elements, but is \"visible\"\n * (in term of DOM point of view) in order to get and to trigger the `focus`\n * DOM event. */\n.selectic__input-value {\n position: fixed;\n opacity: 0;\n z-index: -1000;\n top: -100px;\n}\n\n/* XXX: .form-control has been added to this selector to improve priority and\n * override some rules of the original .form-control */\n.selectic-input.form-control {\n display: inline-flex;\n justify-content: space-between;\n overflow: hidden;\n width: 100%;\n min-height: var(--selectic-input-height);\n padding-top: 0;\n padding-bottom: 0;\n padding-left: 5px;\n line-height: calc(var(--selectic-input-height) - 4px);\n color: var(--selectic-color);\n}\n\n.selectic-input__reverse-icon {\n align-self: center;\n margin-right: 3px;\n cursor: default;\n}\n.selectic-input__clear-icon {\n align-self: center;\n margin-left: 3px;\n cursor: pointer;\n}\n.selectic-input__clear-icon:hover {\n color: var(--selectic-selected-item-color);\n}\n\n.selectic-input.focused {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n\n.selectic-input.disabled {\n cursor: var(--selectic-cursor-disabled);\n background-color: var(--selectic-bg-disabled);\n}\n.selectic-input.disabled .more-items {\n\tbackground-color: var(--selectic-more-items-bg-disabled);\n}\n\n.selectic-input__selected-items {\n display: inline-flex;\n flex-wrap: nowrap;\n align-items: center;\n white-space: nowrap;\n}\n\n.selectic-input__selected-items__placeholder {\n font-style: italic;\n opacity: 0.7;\n white-space: nowrap;\n}\n\n.selectic-icon {\n color: var(--selectic-color);\n text-align: center;\n vertical-align: middle;\n}\n\n.selectic__extended-list {\n position: fixed;\n z-index: 2000;\n height: auto;\n background-color: var(--selectic-bg, #ffffff);\n box-shadow: 2px 5px 12px 0px #888888;\n border-radius: 0 0 4px 4px;\n padding: 0;\n min-width: 200px;\n}\n.selectic__extended-list__list-items {\n max-height: calc(var(--selectic-input-height) * 10);\n
|
|
35
|
+
var css_248z = "/* {{{ Variables */\n\n:root {\n --selectic-font-size: 14px;\n --selectic-cursor-disabled: not-allowed;\n\n /* The main element */\n --selectic-color: #555555;\n --selectic-bg: #ffffff;\n\n /* The main element (when disabled) */\n --selectic-color-disabled: #787878;\n --selectic-bg-disabled: #eeeeee;\n\n /* The list */\n --selectic-panel-bg: #f0f0f0;\n --selectic-separator-bordercolor: #cccccc;\n /* --selectic-item-color: var(--selectic-color); /* Can be set in any CSS configuration */\n\n /* The current selected item */\n --selectic-selected-item-color: #428bca;\n\n /* When mouse is over items or by selecting with key arrows */\n --selectic-active-item-color: #ffffff;\n --selectic-active-item-bg: #66afe9;\n\n /* Selected values in main element */\n --selectic-value-bg: #f0f0f0;\n /* --selectic-more-items-bg: var(--selectic-info-bg); /* can be set in any CSS configuration */\n /* --selectic-more-items-color: var(--selectic-info-color); /* can be set in any CSS configuration */\n --selectic-more-items-bg-disabled: #cccccc;\n\n /* Information message */\n --selectic-info-bg: #5bc0de;\n --selectic-info-color: #ffffff;\n\n /* Error message */\n --selectic-error-bg: #b72c29;\n --selectic-error-color: #ffffff;\n\n /* XXX: Currently it is important to keep this size for a correct scroll\n * height estimation */\n --selectic-input-height: 30px;\n}\n\n/* }}} */\n/* {{{ Bootstrap equivalent style */\n\n.selectic .form-control {\n display: block;\n width: 100%;\n height: calc(var(--selectic-input-height) - 2px);\n font-size: var(--selectic-font-size);\n line-height: 1.42857143;\n color: var(--selectic-color);\n background-color: var(--selectic-bg);\n background-image: none;\n border: 1px solid var(--selectic-separator-bordercolor); /* should use a better variable */\n border-radius: 4px;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n.selectic .has-feedback {\n position: relative;\n}\n.selectic .has-feedback .form-control {\n padding-right: calc(var(--selectic-input-height) + 4px);\n}\n\n.selectic .form-control-feedback.fa,\n.selectic .form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: calc(var(--selectic-input-height) + 4px);\n height: calc(var(--selectic-input-height) + 4px);\n line-height: var(--selectic-input-height);\n text-align: center;\n pointer-events: none;\n}\n\n.selectic .alert-info {\n background-color: var(--selectic-info-bg);\n color: var(--selectic-info-color);\n}\n\n.selectic .alert-danger {\n background-color: var(--selectic-error-bg);\n color: var(--selectic-error-color);\n}\n\n/* }}} */\n\n.selectic * {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.selectic.form-control {\n display: inline-block;\n padding: 0;\n cursor: pointer;\n border: unset;\n}\n\n.has-feedback .selectic__icon-container.form-control-feedback {\n right: 0;\n}\n\n/* The input which contains the selected value\n * XXX: This input should stay hidden behind other elements, but is \"visible\"\n * (in term of DOM point of view) in order to get and to trigger the `focus`\n * DOM event. */\n.selectic__input-value {\n position: fixed;\n opacity: 0;\n z-index: -1000;\n top: -100px;\n}\n\n/* XXX: .form-control has been added to this selector to improve priority and\n * override some rules of the original .form-control */\n.selectic-input.form-control {\n display: inline-flex;\n justify-content: space-between;\n overflow: hidden;\n width: 100%;\n min-height: var(--selectic-input-height);\n padding-top: 0;\n padding-bottom: 0;\n padding-left: 5px;\n line-height: calc(var(--selectic-input-height) - 4px);\n color: var(--selectic-color);\n}\n\n.selectic-input__reverse-icon {\n align-self: center;\n margin-right: 3px;\n cursor: default;\n}\n.selectic-input__clear-icon {\n align-self: center;\n margin-left: 3px;\n cursor: pointer;\n}\n.selectic-input__clear-icon:hover {\n color: var(--selectic-selected-item-color);\n}\n\n.selectic-input.focused {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n\n.selectic-input.disabled {\n cursor: var(--selectic-cursor-disabled);\n background-color: var(--selectic-bg-disabled);\n}\n.selectic-input.disabled .more-items {\n\tbackground-color: var(--selectic-more-items-bg-disabled);\n}\n\n.selectic-input__selected-items {\n display: inline-flex;\n flex-wrap: nowrap;\n align-items: center;\n white-space: nowrap;\n}\n\n.selectic-input__selected-items__placeholder {\n font-style: italic;\n opacity: 0.7;\n white-space: nowrap;\n}\n\n.selectic-icon {\n color: var(--selectic-color);\n text-align: center;\n vertical-align: middle;\n}\n\n.selectic__extended-list {\n position: fixed;\n z-index: 2000;\n height: auto;\n background-color: var(--selectic-bg, #ffffff);\n box-shadow: 2px 5px 12px 0px #888888;\n border-radius: 0 0 4px 4px;\n padding: 0;\n min-width: 200px;\n}\n.selectic__extended-list__list-container{\n overflow: auto;\n}\n.selectic__extended-list__list-items {\n max-height: calc(var(--selectic-input-height) * 10);\n min-width: max-content;\n padding-left: 0;\n}\n\n.selectic-item {\n display: block;\n position: relative;\n box-sizing: border-box;\n padding: 2px 8px;\n color: var(--selectic-item-color, var(--selectic-color));\n min-height: calc(var(--selectic-input-height) - 3px);\n list-style-type: none;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.selectic-item_text {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.selectic-item:not(.selected) .selectic-item_icon {\n opacity: 0;\n}\n\n.selectic-item_text {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.selectic-item__active {\n background-color: var(--selectic-active-item-bg);\n color: var(--selectic-active-item-color);\n}\n.selectic-item__active:not(.selected) .selectic-item_icon {\n opacity: 0.2;\n}\n\n.selectic-item__disabled {\n color: var(--selectic-color-disabled);\n background-color: var(--selectic-bg-disabled);\n}\n\n.selectic-item__is-in-group {\n padding-left: 2em;\n}\n\n.selectic-item__is-group {\n font-weight: bold;\n cursor: default;\n}\n\n.selectic-item.selected {\n color: var(--selectic-selected-item-color);\n}\n.selectic-search-scope {\n color: #e0e0e0;\n left: auto;\n right: 10px;\n}\n\n.selectic__message {\n text-align: center;\n padding: 3px;\n}\n\n.selectic .filter-panel {\n padding: 3px;\n margin-left: 0px;\n margin-right: 0px;\n background-color: var(--selectic-panel-bg);\n border-bottom: 1px solid var(--selectic-separator-bordercolor);\n}\n\n.selectic .panelclosed {\n max-height: 0px;\n transition: max-height 0.3s ease-out;\n overflow: hidden;\n}\n\n.panelopened {\n max-height: 200px;\n transition: max-height 0.3s ease-in;\n overflow: hidden;\n}\n\n.selectic .filter-panel__input {\n padding-left: 0px;\n padding-right: 0px;\n padding-bottom: 10px;\n margin-bottom: 0px;\n}\n.selectic .filter-input {\n height: calc(var(--selectic-input-height) * 0.75);\n}\n\n.selectic .checkbox-filter {\n padding: 5px;\n text-align: center;\n}\n\n.selectic .curtain-handler {\n text-align: center;\n}\n\n.selectic .toggle-selectic {\n margin: 5px;\n padding-left: 0px;\n padding-right: 0px;\n}\n\n.selectic .toggle-boolean-select-all-toggle {\n display: inline;\n margin-right: 15px;\n}\n\n.selectic .toggle-boolean-excluding-toggle {\n display: inline;\n margin-right: 15px;\n}\n\n.selectic .single-value {\n display: grid;\n grid-template: \"value icon\" 1fr / max-content max-content;\n\n padding: 2px;\n padding-left: 5px;\n margin-left: 0;\n margin-right: 5px;\n /* margin top/bottom are mainly to create a gutter in multilines */\n margin-top: 2px;\n margin-bottom: 2px;\n\n border-radius: 3px;\n background-color: var(--selectic-value-bg);\n max-height: calc(var(--selectic-input-height) - 10px);\n max-width: 100%;\n min-width: 30px;\n\n overflow: hidden;\n white-space: nowrap;\n line-height: initial;\n vertical-align: middle;\n}\n\n.selectic .more-items {\n display: inline-block;\n\n padding-left: 5px;\n padding-right: 5px;\n border-radius: 10px;\n\n background-color: var(--selectic-more-items-bg, var(--selectic-info-bg));\n color: var(--selectic-more-items-color, var(--selectic-info-color));\n cursor: help;\n}\n.selectic-input__selected-items__value {\n grid-area: value;\n align-self: center;\n justify-self: normal;\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n}\n\n.selectic-input__selected-items__icon {\n grid-area: icon;\n align-self: center;\n justify-self: center;\n margin-left: 5px;\n}\n.selectic-input__selected-items__icon:hover {\n color: var(--selectic-selected-item-color);\n}\n\n.selectic__label-disabled {\n opacity: 0.5;\n transition: opacity 400ms;\n}\n\n/* XXX: override padding of bootstrap input-sm.\n * This padding introduce a line shift. */\n.selectic.input-sm {\n padding: 0;\n}\n\n/* {{{ overflow multiline */\n\n.selectic--overflow-multiline,\n.selectic--overflow-multiline.form-control,\n.selectic--overflow-multiline .form-control {\n height: unset;\n}\n\n.selectic--overflow-multiline .selectic-input {\n overflow: unset;\n}\n\n.selectic--overflow-multiline .selectic-input__selected-items {\n flex-wrap: wrap;\n}\n\n/* }}} */\n";
|
|
36
36
|
styleInject(css_248z);
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* Clone the object and its inner properties.
|
|
40
40
|
* @param obj The object to be clone.
|
|
41
|
+
* @param attributes list of attributes to not clone.
|
|
41
42
|
* @param refs internal reference to object to avoid cyclic references
|
|
42
43
|
* @returns a copy of obj
|
|
43
44
|
*/
|
|
@@ -299,7 +300,7 @@ class SelecticStore {
|
|
|
299
300
|
const value = deepClone(this.props.value);
|
|
300
301
|
/* set initial value for non reactive attribute */
|
|
301
302
|
this.cacheRequest = new Map();
|
|
302
|
-
const stateParam = deepClone(this.props.params);
|
|
303
|
+
const stateParam = deepClone(this.props.params, ['data']);
|
|
303
304
|
if (stateParam.optionBehavior) {
|
|
304
305
|
this.buildOptionBehavior(stateParam.optionBehavior, stateParam);
|
|
305
306
|
delete stateParam.optionBehavior;
|
|
@@ -444,13 +445,10 @@ class SelecticStore {
|
|
|
444
445
|
selectItem(id, selected, keepOpen = false) {
|
|
445
446
|
const state = this.state;
|
|
446
447
|
let hasChanged = false;
|
|
447
|
-
const
|
|
448
|
+
const item = state.allOptions.find((opt) => opt.id === id);
|
|
448
449
|
/* Check that item is not disabled */
|
|
449
|
-
if (
|
|
450
|
-
|
|
451
|
-
if (item && item.disabled) {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
450
|
+
if (item === null || item === void 0 ? void 0 : item.disabled) {
|
|
451
|
+
return;
|
|
454
452
|
}
|
|
455
453
|
if (state.strictValue && !this.hasValue(id)) {
|
|
456
454
|
/* reject invalid values */
|
|
@@ -468,6 +466,18 @@ class SelecticStore {
|
|
|
468
466
|
hasChanged = internalValue.length > 0;
|
|
469
467
|
}
|
|
470
468
|
else if (selected && !isAlreadySelected) {
|
|
469
|
+
if (item === null || item === void 0 ? void 0 : item.exclusive) {
|
|
470
|
+
/* clear the current selection because the item is exclusive */
|
|
471
|
+
internalValue.splice(0, Infinity);
|
|
472
|
+
}
|
|
473
|
+
else if (internalValue.length === 1) {
|
|
474
|
+
const selectedId = internalValue[0];
|
|
475
|
+
const selectedItem = state.allOptions.find((opt) => opt.id === selectedId);
|
|
476
|
+
if (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.exclusive) {
|
|
477
|
+
/* clear the current selection because the old item was exclusive */
|
|
478
|
+
internalValue.pop();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
471
481
|
internalValue.push(id);
|
|
472
482
|
hasChanged = true;
|
|
473
483
|
}
|
|
@@ -1770,24 +1780,26 @@ let List = class List extends vtyx.Vue {
|
|
|
1770
1780
|
}
|
|
1771
1781
|
/* }}} */
|
|
1772
1782
|
render() {
|
|
1773
|
-
return (vtyx.h("
|
|
1783
|
+
return (vtyx.h("div", { class: "selectic__extended-list__list-container", on: {
|
|
1774
1784
|
scroll: this.checkOffset,
|
|
1775
1785
|
}, ref: "elList" },
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1786
|
+
vtyx.h("ul", { class: "selectic__extended-list__list-items" },
|
|
1787
|
+
!!this.topOffset && (vtyx.h("li", { class: "selectic-item", style: `height:${this.topOffset}px;` })),
|
|
1788
|
+
this.shortOptions.map((option, idx) => (vtyx.h("li", { on: {
|
|
1789
|
+
'click.prevent.stop': () => this.click(option),
|
|
1790
|
+
'mouseover': () => this.onMouseOver(idx),
|
|
1791
|
+
}, class: ['selectic-item', option.className || '', {
|
|
1792
|
+
'selected': option.selected,
|
|
1793
|
+
'selectic-item__active': idx + this.startIndex === this.store.state.activeItemIdx,
|
|
1794
|
+
'selectic-item__disabled': !!option.disabled,
|
|
1795
|
+
'selectic-item__exclusive': !!option.exclusive,
|
|
1796
|
+
'selectic-item__is-in-group': !!option.group,
|
|
1797
|
+
'selectic-item__is-group': option.isGroup,
|
|
1798
|
+
}], style: option.style, title: option.title, key: 'selectic-item-' + (idx + this.startIndex) },
|
|
1799
|
+
this.isMultiple && (vtyx.h("span", { class: "fa fa-fw fa-check selectic-item_icon" })),
|
|
1800
|
+
option.icon && (vtyx.h("span", { class: option.icon })),
|
|
1801
|
+
option.text))),
|
|
1802
|
+
!!this.bottomOffset && (vtyx.h("li", { class: "selectic-item", style: `height:${this.bottomOffset}px;` })))));
|
|
1791
1803
|
}
|
|
1792
1804
|
};
|
|
1793
1805
|
__decorate$2([
|
|
@@ -1987,7 +1999,7 @@ let ExtendedList = class ExtendedList extends vtyx.Vue {
|
|
|
1987
1999
|
return (vtyx.h("div", { style: this.positionStyle, class: "selectic selectic__extended-list" },
|
|
1988
2000
|
!state.hideFilter && (vtyx.h(Filter, { store: this.store })),
|
|
1989
2001
|
isGroup && (vtyx.h("span", { class: "selectic-item selectic-item--header selectic-item__is-group" }, this.topGroup)),
|
|
1990
|
-
vtyx.h(List$1, { store: store,
|
|
2002
|
+
vtyx.h(List$1, { store: store, on: {
|
|
1991
2003
|
groupId: this.getGroup,
|
|
1992
2004
|
} }),
|
|
1993
2005
|
this.infoMessage && (vtyx.h("div", { class: "selectic__message alert-info" }, this.infoMessage)),
|
|
@@ -2264,7 +2276,7 @@ let Selectic = class Selectic extends vtyx.Vue {
|
|
|
2264
2276
|
this.store.props.selectionIsExcluded = this.selectionIsExcluded;
|
|
2265
2277
|
}
|
|
2266
2278
|
onOptionsChange() {
|
|
2267
|
-
this.store.props.options = deepClone(this.options);
|
|
2279
|
+
this.store.props.options = deepClone(this.options, ['data']);
|
|
2268
2280
|
}
|
|
2269
2281
|
onTextsChange() {
|
|
2270
2282
|
const texts = this.texts;
|
|
@@ -2439,7 +2451,7 @@ let Selectic = class Selectic extends vtyx.Vue {
|
|
|
2439
2451
|
var _a, _b, _c;
|
|
2440
2452
|
this._elementsListeners = [];
|
|
2441
2453
|
this.store = new SelecticStore({
|
|
2442
|
-
options: deepClone(this.options),
|
|
2454
|
+
options: deepClone(this.options, ['data']),
|
|
2443
2455
|
value: deepClone(this.value),
|
|
2444
2456
|
selectionIsExcluded: this.selectionIsExcluded,
|
|
2445
2457
|
disabled: this.disabled,
|
package/dist/selectic.esm.js
CHANGED
|
@@ -28,12 +28,13 @@ function styleInject(css, ref) {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
var css_248z = "/* {{{ Variables */\n\n:root {\n --selectic-font-size: 14px;\n --selectic-cursor-disabled: not-allowed;\n\n /* The main element */\n --selectic-color: #555555;\n --selectic-bg: #ffffff;\n\n /* The main element (when disabled) */\n --selectic-color-disabled: #787878;\n --selectic-bg-disabled: #eeeeee;\n\n /* The list */\n --selectic-panel-bg: #f0f0f0;\n --selectic-separator-bordercolor: #cccccc;\n /* --selectic-item-color: var(--selectic-color); /* Can be set in any CSS configuration */\n\n /* The current selected item */\n --selectic-selected-item-color: #428bca;\n\n /* When mouse is over items or by selecting with key arrows */\n --selectic-active-item-color: #ffffff;\n --selectic-active-item-bg: #66afe9;\n\n /* Selected values in main element */\n --selectic-value-bg: #f0f0f0;\n /* --selectic-more-items-bg: var(--selectic-info-bg); /* can be set in any CSS configuration */\n /* --selectic-more-items-color: var(--selectic-info-color); /* can be set in any CSS configuration */\n --selectic-more-items-bg-disabled: #cccccc;\n\n /* Information message */\n --selectic-info-bg: #5bc0de;\n --selectic-info-color: #ffffff;\n\n /* Error message */\n --selectic-error-bg: #b72c29;\n --selectic-error-color: #ffffff;\n\n /* XXX: Currently it is important to keep this size for a correct scroll\n * height estimation */\n --selectic-input-height: 30px;\n}\n\n/* }}} */\n/* {{{ Bootstrap equivalent style */\n\n.selectic .form-control {\n display: block;\n width: 100%;\n height: calc(var(--selectic-input-height) - 2px);\n font-size: var(--selectic-font-size);\n line-height: 1.42857143;\n color: var(--selectic-color);\n background-color: var(--selectic-bg);\n background-image: none;\n border: 1px solid var(--selectic-separator-bordercolor); /* should use a better variable */\n border-radius: 4px;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n.selectic .has-feedback {\n position: relative;\n}\n.selectic .has-feedback .form-control {\n padding-right: calc(var(--selectic-input-height) + 4px);\n}\n\n.selectic .form-control-feedback.fa,\n.selectic .form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: calc(var(--selectic-input-height) + 4px);\n height: calc(var(--selectic-input-height) + 4px);\n line-height: var(--selectic-input-height);\n text-align: center;\n pointer-events: none;\n}\n\n.selectic .alert-info {\n background-color: var(--selectic-info-bg);\n color: var(--selectic-info-color);\n}\n\n.selectic .alert-danger {\n background-color: var(--selectic-error-bg);\n color: var(--selectic-error-color);\n}\n\n/* }}} */\n\n.selectic * {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.selectic.form-control {\n display: inline-block;\n padding: 0;\n cursor: pointer;\n border: unset;\n}\n\n.has-feedback .selectic__icon-container.form-control-feedback {\n right: 0;\n}\n\n/* The input which contains the selected value\n * XXX: This input should stay hidden behind other elements, but is \"visible\"\n * (in term of DOM point of view) in order to get and to trigger the `focus`\n * DOM event. */\n.selectic__input-value {\n position: fixed;\n opacity: 0;\n z-index: -1000;\n top: -100px;\n}\n\n/* XXX: .form-control has been added to this selector to improve priority and\n * override some rules of the original .form-control */\n.selectic-input.form-control {\n display: inline-flex;\n justify-content: space-between;\n overflow: hidden;\n width: 100%;\n min-height: var(--selectic-input-height);\n padding-top: 0;\n padding-bottom: 0;\n padding-left: 5px;\n line-height: calc(var(--selectic-input-height) - 4px);\n color: var(--selectic-color);\n}\n\n.selectic-input__reverse-icon {\n align-self: center;\n margin-right: 3px;\n cursor: default;\n}\n.selectic-input__clear-icon {\n align-self: center;\n margin-left: 3px;\n cursor: pointer;\n}\n.selectic-input__clear-icon:hover {\n color: var(--selectic-selected-item-color);\n}\n\n.selectic-input.focused {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n\n.selectic-input.disabled {\n cursor: var(--selectic-cursor-disabled);\n background-color: var(--selectic-bg-disabled);\n}\n.selectic-input.disabled .more-items {\n\tbackground-color: var(--selectic-more-items-bg-disabled);\n}\n\n.selectic-input__selected-items {\n display: inline-flex;\n flex-wrap: nowrap;\n align-items: center;\n white-space: nowrap;\n}\n\n.selectic-input__selected-items__placeholder {\n font-style: italic;\n opacity: 0.7;\n white-space: nowrap;\n}\n\n.selectic-icon {\n color: var(--selectic-color);\n text-align: center;\n vertical-align: middle;\n}\n\n.selectic__extended-list {\n position: fixed;\n z-index: 2000;\n height: auto;\n background-color: var(--selectic-bg, #ffffff);\n box-shadow: 2px 5px 12px 0px #888888;\n border-radius: 0 0 4px 4px;\n padding: 0;\n min-width: 200px;\n}\n.selectic__extended-list__list-items {\n max-height: calc(var(--selectic-input-height) * 10);\n
|
|
31
|
+
var css_248z = "/* {{{ Variables */\n\n:root {\n --selectic-font-size: 14px;\n --selectic-cursor-disabled: not-allowed;\n\n /* The main element */\n --selectic-color: #555555;\n --selectic-bg: #ffffff;\n\n /* The main element (when disabled) */\n --selectic-color-disabled: #787878;\n --selectic-bg-disabled: #eeeeee;\n\n /* The list */\n --selectic-panel-bg: #f0f0f0;\n --selectic-separator-bordercolor: #cccccc;\n /* --selectic-item-color: var(--selectic-color); /* Can be set in any CSS configuration */\n\n /* The current selected item */\n --selectic-selected-item-color: #428bca;\n\n /* When mouse is over items or by selecting with key arrows */\n --selectic-active-item-color: #ffffff;\n --selectic-active-item-bg: #66afe9;\n\n /* Selected values in main element */\n --selectic-value-bg: #f0f0f0;\n /* --selectic-more-items-bg: var(--selectic-info-bg); /* can be set in any CSS configuration */\n /* --selectic-more-items-color: var(--selectic-info-color); /* can be set in any CSS configuration */\n --selectic-more-items-bg-disabled: #cccccc;\n\n /* Information message */\n --selectic-info-bg: #5bc0de;\n --selectic-info-color: #ffffff;\n\n /* Error message */\n --selectic-error-bg: #b72c29;\n --selectic-error-color: #ffffff;\n\n /* XXX: Currently it is important to keep this size for a correct scroll\n * height estimation */\n --selectic-input-height: 30px;\n}\n\n/* }}} */\n/* {{{ Bootstrap equivalent style */\n\n.selectic .form-control {\n display: block;\n width: 100%;\n height: calc(var(--selectic-input-height) - 2px);\n font-size: var(--selectic-font-size);\n line-height: 1.42857143;\n color: var(--selectic-color);\n background-color: var(--selectic-bg);\n background-image: none;\n border: 1px solid var(--selectic-separator-bordercolor); /* should use a better variable */\n border-radius: 4px;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n.selectic .has-feedback {\n position: relative;\n}\n.selectic .has-feedback .form-control {\n padding-right: calc(var(--selectic-input-height) + 4px);\n}\n\n.selectic .form-control-feedback.fa,\n.selectic .form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: calc(var(--selectic-input-height) + 4px);\n height: calc(var(--selectic-input-height) + 4px);\n line-height: var(--selectic-input-height);\n text-align: center;\n pointer-events: none;\n}\n\n.selectic .alert-info {\n background-color: var(--selectic-info-bg);\n color: var(--selectic-info-color);\n}\n\n.selectic .alert-danger {\n background-color: var(--selectic-error-bg);\n color: var(--selectic-error-color);\n}\n\n/* }}} */\n\n.selectic * {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.selectic.form-control {\n display: inline-block;\n padding: 0;\n cursor: pointer;\n border: unset;\n}\n\n.has-feedback .selectic__icon-container.form-control-feedback {\n right: 0;\n}\n\n/* The input which contains the selected value\n * XXX: This input should stay hidden behind other elements, but is \"visible\"\n * (in term of DOM point of view) in order to get and to trigger the `focus`\n * DOM event. */\n.selectic__input-value {\n position: fixed;\n opacity: 0;\n z-index: -1000;\n top: -100px;\n}\n\n/* XXX: .form-control has been added to this selector to improve priority and\n * override some rules of the original .form-control */\n.selectic-input.form-control {\n display: inline-flex;\n justify-content: space-between;\n overflow: hidden;\n width: 100%;\n min-height: var(--selectic-input-height);\n padding-top: 0;\n padding-bottom: 0;\n padding-left: 5px;\n line-height: calc(var(--selectic-input-height) - 4px);\n color: var(--selectic-color);\n}\n\n.selectic-input__reverse-icon {\n align-self: center;\n margin-right: 3px;\n cursor: default;\n}\n.selectic-input__clear-icon {\n align-self: center;\n margin-left: 3px;\n cursor: pointer;\n}\n.selectic-input__clear-icon:hover {\n color: var(--selectic-selected-item-color);\n}\n\n.selectic-input.focused {\n border-bottom-left-radius: 0px;\n border-bottom-right-radius: 0px;\n}\n\n.selectic-input.disabled {\n cursor: var(--selectic-cursor-disabled);\n background-color: var(--selectic-bg-disabled);\n}\n.selectic-input.disabled .more-items {\n\tbackground-color: var(--selectic-more-items-bg-disabled);\n}\n\n.selectic-input__selected-items {\n display: inline-flex;\n flex-wrap: nowrap;\n align-items: center;\n white-space: nowrap;\n}\n\n.selectic-input__selected-items__placeholder {\n font-style: italic;\n opacity: 0.7;\n white-space: nowrap;\n}\n\n.selectic-icon {\n color: var(--selectic-color);\n text-align: center;\n vertical-align: middle;\n}\n\n.selectic__extended-list {\n position: fixed;\n z-index: 2000;\n height: auto;\n background-color: var(--selectic-bg, #ffffff);\n box-shadow: 2px 5px 12px 0px #888888;\n border-radius: 0 0 4px 4px;\n padding: 0;\n min-width: 200px;\n}\n.selectic__extended-list__list-container{\n overflow: auto;\n}\n.selectic__extended-list__list-items {\n max-height: calc(var(--selectic-input-height) * 10);\n min-width: max-content;\n padding-left: 0;\n}\n\n.selectic-item {\n display: block;\n position: relative;\n box-sizing: border-box;\n padding: 2px 8px;\n color: var(--selectic-item-color, var(--selectic-color));\n min-height: calc(var(--selectic-input-height) - 3px);\n list-style-type: none;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.selectic-item_text {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.selectic-item:not(.selected) .selectic-item_icon {\n opacity: 0;\n}\n\n.selectic-item_text {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n}\n\n.selectic-item__active {\n background-color: var(--selectic-active-item-bg);\n color: var(--selectic-active-item-color);\n}\n.selectic-item__active:not(.selected) .selectic-item_icon {\n opacity: 0.2;\n}\n\n.selectic-item__disabled {\n color: var(--selectic-color-disabled);\n background-color: var(--selectic-bg-disabled);\n}\n\n.selectic-item__is-in-group {\n padding-left: 2em;\n}\n\n.selectic-item__is-group {\n font-weight: bold;\n cursor: default;\n}\n\n.selectic-item.selected {\n color: var(--selectic-selected-item-color);\n}\n.selectic-search-scope {\n color: #e0e0e0;\n left: auto;\n right: 10px;\n}\n\n.selectic__message {\n text-align: center;\n padding: 3px;\n}\n\n.selectic .filter-panel {\n padding: 3px;\n margin-left: 0px;\n margin-right: 0px;\n background-color: var(--selectic-panel-bg);\n border-bottom: 1px solid var(--selectic-separator-bordercolor);\n}\n\n.selectic .panelclosed {\n max-height: 0px;\n transition: max-height 0.3s ease-out;\n overflow: hidden;\n}\n\n.panelopened {\n max-height: 200px;\n transition: max-height 0.3s ease-in;\n overflow: hidden;\n}\n\n.selectic .filter-panel__input {\n padding-left: 0px;\n padding-right: 0px;\n padding-bottom: 10px;\n margin-bottom: 0px;\n}\n.selectic .filter-input {\n height: calc(var(--selectic-input-height) * 0.75);\n}\n\n.selectic .checkbox-filter {\n padding: 5px;\n text-align: center;\n}\n\n.selectic .curtain-handler {\n text-align: center;\n}\n\n.selectic .toggle-selectic {\n margin: 5px;\n padding-left: 0px;\n padding-right: 0px;\n}\n\n.selectic .toggle-boolean-select-all-toggle {\n display: inline;\n margin-right: 15px;\n}\n\n.selectic .toggle-boolean-excluding-toggle {\n display: inline;\n margin-right: 15px;\n}\n\n.selectic .single-value {\n display: grid;\n grid-template: \"value icon\" 1fr / max-content max-content;\n\n padding: 2px;\n padding-left: 5px;\n margin-left: 0;\n margin-right: 5px;\n /* margin top/bottom are mainly to create a gutter in multilines */\n margin-top: 2px;\n margin-bottom: 2px;\n\n border-radius: 3px;\n background-color: var(--selectic-value-bg);\n max-height: calc(var(--selectic-input-height) - 10px);\n max-width: 100%;\n min-width: 30px;\n\n overflow: hidden;\n white-space: nowrap;\n line-height: initial;\n vertical-align: middle;\n}\n\n.selectic .more-items {\n display: inline-block;\n\n padding-left: 5px;\n padding-right: 5px;\n border-radius: 10px;\n\n background-color: var(--selectic-more-items-bg, var(--selectic-info-bg));\n color: var(--selectic-more-items-color, var(--selectic-info-color));\n cursor: help;\n}\n.selectic-input__selected-items__value {\n grid-area: value;\n align-self: center;\n justify-self: normal;\n text-overflow: ellipsis;\n overflow: hidden;\n white-space: nowrap;\n}\n\n.selectic-input__selected-items__icon {\n grid-area: icon;\n align-self: center;\n justify-self: center;\n margin-left: 5px;\n}\n.selectic-input__selected-items__icon:hover {\n color: var(--selectic-selected-item-color);\n}\n\n.selectic__label-disabled {\n opacity: 0.5;\n transition: opacity 400ms;\n}\n\n/* XXX: override padding of bootstrap input-sm.\n * This padding introduce a line shift. */\n.selectic.input-sm {\n padding: 0;\n}\n\n/* {{{ overflow multiline */\n\n.selectic--overflow-multiline,\n.selectic--overflow-multiline.form-control,\n.selectic--overflow-multiline .form-control {\n height: unset;\n}\n\n.selectic--overflow-multiline .selectic-input {\n overflow: unset;\n}\n\n.selectic--overflow-multiline .selectic-input__selected-items {\n flex-wrap: wrap;\n}\n\n/* }}} */\n";
|
|
32
32
|
styleInject(css_248z);
|
|
33
33
|
|
|
34
34
|
/**
|
|
35
35
|
* Clone the object and its inner properties.
|
|
36
36
|
* @param obj The object to be clone.
|
|
37
|
+
* @param attributes list of attributes to not clone.
|
|
37
38
|
* @param refs internal reference to object to avoid cyclic references
|
|
38
39
|
* @returns a copy of obj
|
|
39
40
|
*/
|
|
@@ -295,7 +296,7 @@ class SelecticStore {
|
|
|
295
296
|
const value = deepClone(this.props.value);
|
|
296
297
|
/* set initial value for non reactive attribute */
|
|
297
298
|
this.cacheRequest = new Map();
|
|
298
|
-
const stateParam = deepClone(this.props.params);
|
|
299
|
+
const stateParam = deepClone(this.props.params, ['data']);
|
|
299
300
|
if (stateParam.optionBehavior) {
|
|
300
301
|
this.buildOptionBehavior(stateParam.optionBehavior, stateParam);
|
|
301
302
|
delete stateParam.optionBehavior;
|
|
@@ -440,13 +441,10 @@ class SelecticStore {
|
|
|
440
441
|
selectItem(id, selected, keepOpen = false) {
|
|
441
442
|
const state = this.state;
|
|
442
443
|
let hasChanged = false;
|
|
443
|
-
const
|
|
444
|
+
const item = state.allOptions.find((opt) => opt.id === id);
|
|
444
445
|
/* Check that item is not disabled */
|
|
445
|
-
if (
|
|
446
|
-
|
|
447
|
-
if (item && item.disabled) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
446
|
+
if (item === null || item === void 0 ? void 0 : item.disabled) {
|
|
447
|
+
return;
|
|
450
448
|
}
|
|
451
449
|
if (state.strictValue && !this.hasValue(id)) {
|
|
452
450
|
/* reject invalid values */
|
|
@@ -464,6 +462,18 @@ class SelecticStore {
|
|
|
464
462
|
hasChanged = internalValue.length > 0;
|
|
465
463
|
}
|
|
466
464
|
else if (selected && !isAlreadySelected) {
|
|
465
|
+
if (item === null || item === void 0 ? void 0 : item.exclusive) {
|
|
466
|
+
/* clear the current selection because the item is exclusive */
|
|
467
|
+
internalValue.splice(0, Infinity);
|
|
468
|
+
}
|
|
469
|
+
else if (internalValue.length === 1) {
|
|
470
|
+
const selectedId = internalValue[0];
|
|
471
|
+
const selectedItem = state.allOptions.find((opt) => opt.id === selectedId);
|
|
472
|
+
if (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.exclusive) {
|
|
473
|
+
/* clear the current selection because the old item was exclusive */
|
|
474
|
+
internalValue.pop();
|
|
475
|
+
}
|
|
476
|
+
}
|
|
467
477
|
internalValue.push(id);
|
|
468
478
|
hasChanged = true;
|
|
469
479
|
}
|
|
@@ -1766,24 +1776,26 @@ let List = class List extends Vue {
|
|
|
1766
1776
|
}
|
|
1767
1777
|
/* }}} */
|
|
1768
1778
|
render() {
|
|
1769
|
-
return (h("
|
|
1779
|
+
return (h("div", { class: "selectic__extended-list__list-container", on: {
|
|
1770
1780
|
scroll: this.checkOffset,
|
|
1771
1781
|
}, ref: "elList" },
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1782
|
+
h("ul", { class: "selectic__extended-list__list-items" },
|
|
1783
|
+
!!this.topOffset && (h("li", { class: "selectic-item", style: `height:${this.topOffset}px;` })),
|
|
1784
|
+
this.shortOptions.map((option, idx) => (h("li", { on: {
|
|
1785
|
+
'click.prevent.stop': () => this.click(option),
|
|
1786
|
+
'mouseover': () => this.onMouseOver(idx),
|
|
1787
|
+
}, class: ['selectic-item', option.className || '', {
|
|
1788
|
+
'selected': option.selected,
|
|
1789
|
+
'selectic-item__active': idx + this.startIndex === this.store.state.activeItemIdx,
|
|
1790
|
+
'selectic-item__disabled': !!option.disabled,
|
|
1791
|
+
'selectic-item__exclusive': !!option.exclusive,
|
|
1792
|
+
'selectic-item__is-in-group': !!option.group,
|
|
1793
|
+
'selectic-item__is-group': option.isGroup,
|
|
1794
|
+
}], style: option.style, title: option.title, key: 'selectic-item-' + (idx + this.startIndex) },
|
|
1795
|
+
this.isMultiple && (h("span", { class: "fa fa-fw fa-check selectic-item_icon" })),
|
|
1796
|
+
option.icon && (h("span", { class: option.icon })),
|
|
1797
|
+
option.text))),
|
|
1798
|
+
!!this.bottomOffset && (h("li", { class: "selectic-item", style: `height:${this.bottomOffset}px;` })))));
|
|
1787
1799
|
}
|
|
1788
1800
|
};
|
|
1789
1801
|
__decorate$2([
|
|
@@ -1983,7 +1995,7 @@ let ExtendedList = class ExtendedList extends Vue {
|
|
|
1983
1995
|
return (h("div", { style: this.positionStyle, class: "selectic selectic__extended-list" },
|
|
1984
1996
|
!state.hideFilter && (h(Filter, { store: this.store })),
|
|
1985
1997
|
isGroup && (h("span", { class: "selectic-item selectic-item--header selectic-item__is-group" }, this.topGroup)),
|
|
1986
|
-
h(List$1, { store: store,
|
|
1998
|
+
h(List$1, { store: store, on: {
|
|
1987
1999
|
groupId: this.getGroup,
|
|
1988
2000
|
} }),
|
|
1989
2001
|
this.infoMessage && (h("div", { class: "selectic__message alert-info" }, this.infoMessage)),
|
|
@@ -2260,7 +2272,7 @@ let Selectic = class Selectic extends Vue {
|
|
|
2260
2272
|
this.store.props.selectionIsExcluded = this.selectionIsExcluded;
|
|
2261
2273
|
}
|
|
2262
2274
|
onOptionsChange() {
|
|
2263
|
-
this.store.props.options = deepClone(this.options);
|
|
2275
|
+
this.store.props.options = deepClone(this.options, ['data']);
|
|
2264
2276
|
}
|
|
2265
2277
|
onTextsChange() {
|
|
2266
2278
|
const texts = this.texts;
|
|
@@ -2435,7 +2447,7 @@ let Selectic = class Selectic extends Vue {
|
|
|
2435
2447
|
var _a, _b, _c;
|
|
2436
2448
|
this._elementsListeners = [];
|
|
2437
2449
|
this.store = new SelecticStore({
|
|
2438
|
-
options: deepClone(this.options),
|
|
2450
|
+
options: deepClone(this.options, ['data']),
|
|
2439
2451
|
value: deepClone(this.value),
|
|
2440
2452
|
selectionIsExcluded: this.selectionIsExcluded,
|
|
2441
2453
|
disabled: this.disabled,
|
package/doc/list.md
CHANGED
|
@@ -25,12 +25,13 @@ It is possible to define the `option` more precisely.
|
|
|
25
25
|
* **id** {`string | number`} _(mandatory)_: The option identifier. *It is important that it is unique among all other options*.
|
|
26
26
|
* **text** {`string`} _(mandatory)_: The text which is displayed to select the option or when it is selected.
|
|
27
27
|
* **title** {`string`}: Text displayed in `title` when cursor is over the option (default: `''`).
|
|
28
|
-
* **disabled** {`boolean`}: if `true
|
|
28
|
+
* **disabled** {`boolean`}: if `true`, this option cannot be selected (default: `false`).
|
|
29
29
|
* **className** {`string`}: `class` that are applied on the option (default: `''`).
|
|
30
30
|
* **style** {`string`}: css style which are applied on the option (default: `''`).
|
|
31
31
|
* **icon** {`string`}: class names which are applied on a `<span>` before text in the option to display an icon (default: `''`).
|
|
32
32
|
* **options** {`options[]`}: an other list of options. The current option is considered as a group (equivalent of `optgroup`) (default: `undefined`).
|
|
33
|
-
* **group** {`string | number`}: If set the option is part of the given group. This property is needed only in dynamic mode if the option is part of an optgroup (default: `null`).
|
|
33
|
+
* **group** {`string | number`}: If set, the option is part of the given group. This property is needed only in dynamic mode if the option is part of an optgroup (default: `null`).
|
|
34
|
+
* **exclusive** {`boolean`}: If set to `true`, in multiple mode, this option will be the only one selected. It means that it clears the previous selected options, and if another option is selected, this option is no more selected.
|
|
34
35
|
* **data** {`any`}: You can store any information here, it will be provided when getting selected options. _It is not used by selectic so it can be anything you want_ (default: `undefined`).
|
|
35
36
|
|
|
36
37
|
```javascript
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selectic",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.16",
|
|
4
4
|
"description": "Smart Select for VueJS 3.x",
|
|
5
5
|
"main": "dist/selectic.common.js",
|
|
6
6
|
"module": "dist/selectic.esm.js",
|
|
@@ -41,10 +41,10 @@
|
|
|
41
41
|
"vtyx": "4.0.5"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@babel/types": "^7.
|
|
45
|
-
"rollup": "^2.
|
|
44
|
+
"@babel/types": "^7.19.4",
|
|
45
|
+
"rollup": "^2.79.1",
|
|
46
46
|
"rollup-plugin-postcss": "^3.1.8",
|
|
47
|
-
"tape": "^4.
|
|
47
|
+
"tape": "^4.16.1",
|
|
48
48
|
"typescript": "~4.5"
|
|
49
49
|
}
|
|
50
50
|
}
|
package/src/ExtendedList.tsx
CHANGED
|
@@ -255,6 +255,7 @@ export default class ExtendedList extends Vue<Props> {
|
|
|
255
255
|
store={this.store}
|
|
256
256
|
/>
|
|
257
257
|
)}
|
|
258
|
+
|
|
258
259
|
{isGroup && (
|
|
259
260
|
<span
|
|
260
261
|
class="selectic-item selectic-item--header selectic-item__is-group"
|
|
@@ -264,7 +265,6 @@ export default class ExtendedList extends Vue<Props> {
|
|
|
264
265
|
)}
|
|
265
266
|
<List
|
|
266
267
|
store={store}
|
|
267
|
-
class="selectic__extended-list__list-items"
|
|
268
268
|
on={{
|
|
269
269
|
groupId: this.getGroup,
|
|
270
270
|
}}
|
package/src/List.tsx
CHANGED
|
@@ -22,7 +22,7 @@ export interface Props {
|
|
|
22
22
|
@Component
|
|
23
23
|
export default class List extends Vue<Props> {
|
|
24
24
|
public $refs: {
|
|
25
|
-
elList:
|
|
25
|
+
elList: HTMLDivElement;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
/* {{{ props */
|
|
@@ -241,53 +241,59 @@ export default class List extends Vue<Props> {
|
|
|
241
241
|
|
|
242
242
|
public render() {
|
|
243
243
|
return (
|
|
244
|
-
<
|
|
244
|
+
<div
|
|
245
|
+
class="selectic__extended-list__list-container"
|
|
245
246
|
on={{
|
|
246
247
|
scroll: this.checkOffset,
|
|
247
248
|
}}
|
|
248
249
|
ref="elList"
|
|
249
250
|
>
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
class="selectic-item"
|
|
253
|
-
style={`height:${this.topOffset}px;`}
|
|
254
|
-
></li>
|
|
255
|
-
)}
|
|
256
|
-
{this.shortOptions.map((option, idx) => (
|
|
257
|
-
<li
|
|
258
|
-
on={{
|
|
259
|
-
'click.prevent.stop': () => this.click(option),
|
|
260
|
-
'mouseover': () => this.onMouseOver(idx),
|
|
261
|
-
}}
|
|
262
|
-
class={['selectic-item', option.className || '', {
|
|
263
|
-
'selected': option.selected,
|
|
264
|
-
'selectic-item__active': idx + this.startIndex === this.store.state.activeItemIdx,
|
|
265
|
-
'selectic-item__disabled': !!option.disabled,
|
|
266
|
-
'selectic-item__is-in-group': !!option.group,
|
|
267
|
-
'selectic-item__is-group': option.isGroup,
|
|
268
|
-
}]}
|
|
269
|
-
style={option.style}
|
|
270
|
-
title={option.title}
|
|
271
|
-
key={'selectic-item-' + (idx + this.startIndex)}
|
|
251
|
+
<ul
|
|
252
|
+
class="selectic__extended-list__list-items"
|
|
272
253
|
>
|
|
273
|
-
|
|
274
|
-
<
|
|
275
|
-
class="
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
254
|
+
{!!this.topOffset && (
|
|
255
|
+
<li
|
|
256
|
+
class="selectic-item"
|
|
257
|
+
style={`height:${this.topOffset}px;`}
|
|
258
|
+
></li>
|
|
259
|
+
)}
|
|
260
|
+
{this.shortOptions.map((option, idx) => (
|
|
261
|
+
<li
|
|
262
|
+
on={{
|
|
263
|
+
'click.prevent.stop': () => this.click(option),
|
|
264
|
+
'mouseover': () => this.onMouseOver(idx),
|
|
265
|
+
}}
|
|
266
|
+
class={['selectic-item', option.className || '', {
|
|
267
|
+
'selected': option.selected,
|
|
268
|
+
'selectic-item__active': idx + this.startIndex === this.store.state.activeItemIdx,
|
|
269
|
+
'selectic-item__disabled': !!option.disabled,
|
|
270
|
+
'selectic-item__exclusive': !!option.exclusive,
|
|
271
|
+
'selectic-item__is-in-group': !!option.group,
|
|
272
|
+
'selectic-item__is-group': option.isGroup,
|
|
273
|
+
}]}
|
|
274
|
+
style={option.style}
|
|
275
|
+
title={option.title}
|
|
276
|
+
key={'selectic-item-' + (idx + this.startIndex)}
|
|
277
|
+
>
|
|
278
|
+
{this.isMultiple && (
|
|
279
|
+
<span
|
|
280
|
+
class="fa fa-fw fa-check selectic-item_icon"
|
|
281
|
+
></span>
|
|
282
|
+
)}
|
|
283
|
+
{option.icon && (
|
|
284
|
+
<span class={option.icon}></span>
|
|
285
|
+
)}
|
|
286
|
+
{option.text}
|
|
287
|
+
</li>
|
|
288
|
+
))}
|
|
289
|
+
{!!this.bottomOffset && (
|
|
290
|
+
<li
|
|
291
|
+
class="selectic-item"
|
|
292
|
+
style={`height:${this.bottomOffset}px;`}
|
|
293
|
+
></li>
|
|
294
|
+
)}
|
|
295
|
+
</ul>
|
|
296
|
+
</div>
|
|
291
297
|
);
|
|
292
298
|
}
|
|
293
299
|
}
|
package/src/Store.tsx
CHANGED
|
@@ -29,6 +29,7 @@ export interface OptionValue {
|
|
|
29
29
|
style?: string;
|
|
30
30
|
icon?: string;
|
|
31
31
|
options?: OptionValue[];
|
|
32
|
+
exclusive?: boolean;
|
|
32
33
|
|
|
33
34
|
/* Used to store specific information about this option.
|
|
34
35
|
* This `data` is not used by Selectic. */
|
|
@@ -593,7 +594,7 @@ export default class SelecticStore {
|
|
|
593
594
|
this.cacheRequest = new Map();
|
|
594
595
|
|
|
595
596
|
const stateParam: SelecticStoreStateParams | SelecticStoreState =
|
|
596
|
-
deepClone(this.props.params);
|
|
597
|
+
deepClone(this.props.params, ['data']);
|
|
597
598
|
|
|
598
599
|
if (stateParam.optionBehavior) {
|
|
599
600
|
this.buildOptionBehavior(
|
|
@@ -766,14 +767,11 @@ export default class SelecticStore {
|
|
|
766
767
|
public selectItem(id: OptionId, selected?: boolean, keepOpen = false) {
|
|
767
768
|
const state = this.state;
|
|
768
769
|
let hasChanged = false;
|
|
769
|
-
const
|
|
770
|
+
const item = state.allOptions.find((opt) => opt.id === id);
|
|
770
771
|
|
|
771
772
|
/* Check that item is not disabled */
|
|
772
|
-
if (
|
|
773
|
-
|
|
774
|
-
if (item && item.disabled) {
|
|
775
|
-
return;
|
|
776
|
-
}
|
|
773
|
+
if (item?.disabled) {
|
|
774
|
+
return;
|
|
777
775
|
}
|
|
778
776
|
|
|
779
777
|
if (state.strictValue && !this.hasValue(id)) {
|
|
@@ -795,6 +793,17 @@ export default class SelecticStore {
|
|
|
795
793
|
hasChanged = internalValue.length > 0;
|
|
796
794
|
} else
|
|
797
795
|
if (selected && !isAlreadySelected) {
|
|
796
|
+
if (item?.exclusive) {
|
|
797
|
+
/* clear the current selection because the item is exclusive */
|
|
798
|
+
internalValue.splice(0, Infinity);
|
|
799
|
+
} else if (internalValue.length === 1) {
|
|
800
|
+
const selectedId = internalValue[0];
|
|
801
|
+
const selectedItem = state.allOptions.find((opt) => opt.id === selectedId);
|
|
802
|
+
if (selectedItem?.exclusive) {
|
|
803
|
+
/* clear the current selection because the old item was exclusive */
|
|
804
|
+
internalValue.pop();
|
|
805
|
+
}
|
|
806
|
+
}
|
|
798
807
|
internalValue.push(id);
|
|
799
808
|
hasChanged = true;
|
|
800
809
|
} else
|
package/src/css/selectic.css
CHANGED
|
@@ -192,9 +192,12 @@
|
|
|
192
192
|
padding: 0;
|
|
193
193
|
min-width: 200px;
|
|
194
194
|
}
|
|
195
|
+
.selectic__extended-list__list-container{
|
|
196
|
+
overflow: auto;
|
|
197
|
+
}
|
|
195
198
|
.selectic__extended-list__list-items {
|
|
196
199
|
max-height: calc(var(--selectic-input-height) * 10);
|
|
197
|
-
|
|
200
|
+
min-width: max-content;
|
|
198
201
|
padding-left: 0;
|
|
199
202
|
}
|
|
200
203
|
|
package/src/index.tsx
CHANGED
|
@@ -561,7 +561,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
561
561
|
|
|
562
562
|
@Watch('options', { deep: true })
|
|
563
563
|
public onOptionsChange() {
|
|
564
|
-
this.store.props.options = deepClone(this.options);
|
|
564
|
+
this.store.props.options = deepClone(this.options, ['data']);
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
@Watch('texts', { deep: true })
|
|
@@ -782,7 +782,7 @@ export default class Selectic extends Vue<Props> {
|
|
|
782
782
|
this._elementsListeners = [];
|
|
783
783
|
|
|
784
784
|
this.store = new Store({
|
|
785
|
-
options: deepClone(this.options),
|
|
785
|
+
options: deepClone(this.options, ['data']),
|
|
786
786
|
value: deepClone(this.value),
|
|
787
787
|
selectionIsExcluded: this.selectionIsExcluded,
|
|
788
788
|
disabled: this.disabled,
|
package/src/tools.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { unref } from 'vue';
|
|
|
3
3
|
/**
|
|
4
4
|
* Clone the object and its inner properties.
|
|
5
5
|
* @param obj The object to be clone.
|
|
6
|
+
* @param attributes list of attributes to not clone.
|
|
6
7
|
* @param refs internal reference to object to avoid cyclic references
|
|
7
8
|
* @returns a copy of obj
|
|
8
9
|
*/
|
|
@@ -202,8 +202,10 @@ tape.test('selectItem()', (st) => {
|
|
|
202
202
|
|
|
203
203
|
st.test('when "multiple" is true', (sTest) => {
|
|
204
204
|
function getStore() {
|
|
205
|
-
const options = getOptions(
|
|
205
|
+
const options = getOptions(8);
|
|
206
206
|
options[4].disabled = true;
|
|
207
|
+
options[6].exclusive = true;
|
|
208
|
+
options[7].exclusive = true;
|
|
207
209
|
|
|
208
210
|
const store = new Store({
|
|
209
211
|
options: options,
|
|
@@ -363,7 +365,6 @@ tape.test('selectItem()', (st) => {
|
|
|
363
365
|
t.end();
|
|
364
366
|
});
|
|
365
367
|
|
|
366
|
-
|
|
367
368
|
sTest.test('should clear selection', (t) => {
|
|
368
369
|
const store = getStore();
|
|
369
370
|
store.state.internalValue = [1, 4];
|
|
@@ -412,5 +413,29 @@ tape.test('selectItem()', (st) => {
|
|
|
412
413
|
t.is(store.state.status.hasChanged, false);
|
|
413
414
|
t.end();
|
|
414
415
|
});
|
|
416
|
+
|
|
417
|
+
sTest.test('should keep only exclusive item', (t) => {
|
|
418
|
+
const store = getStore();
|
|
419
|
+
store.state.internalValue = [1, 4, 5];
|
|
420
|
+
|
|
421
|
+
store.selectItem(6, true);
|
|
422
|
+
t.deepEqual(store.state.internalValue, [6]);
|
|
423
|
+
t.is(store.state.status.hasChanged, true);
|
|
424
|
+
|
|
425
|
+
store.selectItem(7, true);
|
|
426
|
+
t.deepEqual(store.state.internalValue, [7]);
|
|
427
|
+
t.is(store.state.status.hasChanged, true);
|
|
428
|
+
|
|
429
|
+
store.selectItem(1, true);
|
|
430
|
+
t.deepEqual(store.state.internalValue, [1]);
|
|
431
|
+
t.is(store.state.status.hasChanged, true);
|
|
432
|
+
|
|
433
|
+
store.selectItem(5, true);
|
|
434
|
+
t.deepEqual(store.state.internalValue, [1, 5]);
|
|
435
|
+
t.is(store.state.status.hasChanged, true);
|
|
436
|
+
|
|
437
|
+
t.is(store.state.selectionIsExcluded, false);
|
|
438
|
+
t.end();
|
|
439
|
+
});
|
|
415
440
|
});
|
|
416
441
|
});
|
package/types/List.d.ts
CHANGED
package/types/Store.d.ts
CHANGED
package/types/tools.d.ts
CHANGED