selectic 3.0.15 → 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 +35 -24
- package/dist/selectic.esm.js +35 -24
- 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 +15 -6
- package/src/css/selectic.css +4 -1
- package/test/Store/selectItem.spec.js +27 -2
- package/types/List.d.ts +1 -1
- package/types/Store.d.ts +1 -0
package/dist/selectic.common.js
CHANGED
|
@@ -32,7 +32,7 @@ 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
|
/**
|
|
@@ -445,13 +445,10 @@ class SelecticStore {
|
|
|
445
445
|
selectItem(id, selected, keepOpen = false) {
|
|
446
446
|
const state = this.state;
|
|
447
447
|
let hasChanged = false;
|
|
448
|
-
const
|
|
448
|
+
const item = state.allOptions.find((opt) => opt.id === id);
|
|
449
449
|
/* Check that item is not disabled */
|
|
450
|
-
if (
|
|
451
|
-
|
|
452
|
-
if (item && item.disabled) {
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
450
|
+
if (item === null || item === void 0 ? void 0 : item.disabled) {
|
|
451
|
+
return;
|
|
455
452
|
}
|
|
456
453
|
if (state.strictValue && !this.hasValue(id)) {
|
|
457
454
|
/* reject invalid values */
|
|
@@ -469,6 +466,18 @@ class SelecticStore {
|
|
|
469
466
|
hasChanged = internalValue.length > 0;
|
|
470
467
|
}
|
|
471
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
|
+
}
|
|
472
481
|
internalValue.push(id);
|
|
473
482
|
hasChanged = true;
|
|
474
483
|
}
|
|
@@ -1771,24 +1780,26 @@ let List = class List extends vtyx.Vue {
|
|
|
1771
1780
|
}
|
|
1772
1781
|
/* }}} */
|
|
1773
1782
|
render() {
|
|
1774
|
-
return (vtyx.h("
|
|
1783
|
+
return (vtyx.h("div", { class: "selectic__extended-list__list-container", on: {
|
|
1775
1784
|
scroll: this.checkOffset,
|
|
1776
1785
|
}, ref: "elList" },
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
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;` })))));
|
|
1792
1803
|
}
|
|
1793
1804
|
};
|
|
1794
1805
|
__decorate$2([
|
|
@@ -1988,7 +1999,7 @@ let ExtendedList = class ExtendedList extends vtyx.Vue {
|
|
|
1988
1999
|
return (vtyx.h("div", { style: this.positionStyle, class: "selectic selectic__extended-list" },
|
|
1989
2000
|
!state.hideFilter && (vtyx.h(Filter, { store: this.store })),
|
|
1990
2001
|
isGroup && (vtyx.h("span", { class: "selectic-item selectic-item--header selectic-item__is-group" }, this.topGroup)),
|
|
1991
|
-
vtyx.h(List$1, { store: store,
|
|
2002
|
+
vtyx.h(List$1, { store: store, on: {
|
|
1992
2003
|
groupId: this.getGroup,
|
|
1993
2004
|
} }),
|
|
1994
2005
|
this.infoMessage && (vtyx.h("div", { class: "selectic__message alert-info" }, this.infoMessage)),
|
package/dist/selectic.esm.js
CHANGED
|
@@ -28,7 +28,7 @@ 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
|
/**
|
|
@@ -441,13 +441,10 @@ class SelecticStore {
|
|
|
441
441
|
selectItem(id, selected, keepOpen = false) {
|
|
442
442
|
const state = this.state;
|
|
443
443
|
let hasChanged = false;
|
|
444
|
-
const
|
|
444
|
+
const item = state.allOptions.find((opt) => opt.id === id);
|
|
445
445
|
/* Check that item is not disabled */
|
|
446
|
-
if (
|
|
447
|
-
|
|
448
|
-
if (item && item.disabled) {
|
|
449
|
-
return;
|
|
450
|
-
}
|
|
446
|
+
if (item === null || item === void 0 ? void 0 : item.disabled) {
|
|
447
|
+
return;
|
|
451
448
|
}
|
|
452
449
|
if (state.strictValue && !this.hasValue(id)) {
|
|
453
450
|
/* reject invalid values */
|
|
@@ -465,6 +462,18 @@ class SelecticStore {
|
|
|
465
462
|
hasChanged = internalValue.length > 0;
|
|
466
463
|
}
|
|
467
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
|
+
}
|
|
468
477
|
internalValue.push(id);
|
|
469
478
|
hasChanged = true;
|
|
470
479
|
}
|
|
@@ -1767,24 +1776,26 @@ let List = class List extends Vue {
|
|
|
1767
1776
|
}
|
|
1768
1777
|
/* }}} */
|
|
1769
1778
|
render() {
|
|
1770
|
-
return (h("
|
|
1779
|
+
return (h("div", { class: "selectic__extended-list__list-container", on: {
|
|
1771
1780
|
scroll: this.checkOffset,
|
|
1772
1781
|
}, ref: "elList" },
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
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;` })))));
|
|
1788
1799
|
}
|
|
1789
1800
|
};
|
|
1790
1801
|
__decorate$2([
|
|
@@ -1984,7 +1995,7 @@ let ExtendedList = class ExtendedList extends Vue {
|
|
|
1984
1995
|
return (h("div", { style: this.positionStyle, class: "selectic selectic__extended-list" },
|
|
1985
1996
|
!state.hideFilter && (h(Filter, { store: this.store })),
|
|
1986
1997
|
isGroup && (h("span", { class: "selectic-item selectic-item--header selectic-item__is-group" }, this.topGroup)),
|
|
1987
|
-
h(List$1, { store: store,
|
|
1998
|
+
h(List$1, { store: store, on: {
|
|
1988
1999
|
groupId: this.getGroup,
|
|
1989
2000
|
} }),
|
|
1990
2001
|
this.infoMessage && (h("div", { class: "selectic__message alert-info" }, this.infoMessage)),
|
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. */
|
|
@@ -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
|
|
|
@@ -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