selectic 3.1.2 → 3.1.4
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 +129 -61
- package/dist/selectic.esm.js +129 -61
- package/doc/list.md +2 -1
- package/package.json +2 -1
- package/src/ExtendedList.tsx +40 -42
- package/src/MainInput.tsx +27 -4
- package/src/Store.tsx +64 -13
- package/src/css/selectic.css +3 -0
- package/src/index.tsx +21 -10
- package/test/Store/Store_creation.spec.js +74 -0
- package/test/Store/selectItem.spec.js +108 -22
- package/types/ExtendedList.d.ts +1 -1
- package/types/MainInput.d.ts +2 -1
- package/types/index.d.ts +1 -1
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 top: var(--top-position, 0);\n z-index: 2000;\n height: auto;\n max-height: var(--availableSpace);\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 width: var(--list-width, 200px);\n min-width: 200px;\n display: grid;\n grid-template-rows: minmax(0, max-content) 1fr;\n}\n.selectic__extended-list.selectic-position-top {\n box-shadow: 2px -3px 12px 0px #888888;\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__is-group.selectable {\n cursor: pointer;\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.selectic .form-control-feedback.fa.selectic-search-scope {\n width: calc(var(--selectic-input-height) * 0.75);\n height: calc(var(--selectic-input-height) * 0.75);\n line-height: calc(var(--selectic-input-height) * 0.75);\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/* {{{ icons */\n\n@keyframes selectic-animation-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(359deg);\n }\n}\n\n.selectic__icon {\n height: 1em;\n fill: currentColor;\n}\n\n.selectic-spin {\n animation: selectic-animation-spin 2s infinite linear;\n}\n\n/* }}} */\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 top: var(--top-position, 0);\n z-index: 2000;\n height: auto;\n max-height: var(--availableSpace);\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 width: var(--list-width, 200px);\n min-width: 200px;\n display: grid;\n grid-template-rows: minmax(0, max-content) 1fr;\n}\n.selectic__extended-list.selectic-position-top {\n box-shadow: 2px -3px 12px 0px #888888;\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.selectic-item__active.selectic-item__disabled:not(.selected) .selectic-item_icon {\n opacity: 0;\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__is-group.selectable {\n cursor: pointer;\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.selectic .form-control-feedback.fa.selectic-search-scope {\n width: calc(var(--selectic-input-height) * 0.75);\n height: calc(var(--selectic-input-height) * 0.75);\n line-height: calc(var(--selectic-input-height) * 0.75);\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/* {{{ icons */\n\n@keyframes selectic-animation-spin {\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(359deg);\n }\n}\n\n.selectic__icon {\n height: 1em;\n fill: currentColor;\n}\n\n.selectic-spin {\n animation: selectic-animation-spin 2s infinite linear;\n}\n\n/* }}} */\n";
|
|
32
32
|
styleInject(css_248z);
|
|
33
33
|
|
|
34
34
|
/**
|
|
@@ -554,25 +554,54 @@ class SelecticStore {
|
|
|
554
554
|
if (selected === undefined) {
|
|
555
555
|
selected = !isAlreadySelected;
|
|
556
556
|
}
|
|
557
|
+
const selectedOptions = Array.isArray(state.selectedOptions)
|
|
558
|
+
? state.selectedOptions
|
|
559
|
+
: [];
|
|
557
560
|
if (id === null) {
|
|
558
|
-
|
|
559
|
-
|
|
561
|
+
/* Keep disabled items: we cannot removed them because they
|
|
562
|
+
* are disabled */
|
|
563
|
+
const newSelection = selectedOptions.reduce((list, item) => {
|
|
564
|
+
if (item.disabled && item.id) {
|
|
565
|
+
list.push(item.id);
|
|
566
|
+
}
|
|
567
|
+
return list;
|
|
568
|
+
}, []);
|
|
569
|
+
state.internalValue = newSelection;
|
|
570
|
+
hasChanged = internalValue.length > newSelection.length;
|
|
560
571
|
}
|
|
561
572
|
else if (selected && !isAlreadySelected) {
|
|
573
|
+
let addItem = true;
|
|
562
574
|
if (item === null || item === void 0 ? void 0 : item.exclusive) {
|
|
563
|
-
|
|
564
|
-
|
|
575
|
+
const hasDisabledSelected = selectedOptions.some((opt) => {
|
|
576
|
+
return opt.disabled;
|
|
577
|
+
});
|
|
578
|
+
if (hasDisabledSelected) {
|
|
579
|
+
/* do not remove disabled item from selection */
|
|
580
|
+
addItem = false;
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
/* clear the current selection because the item is exclusive */
|
|
584
|
+
internalValue.splice(0, Infinity);
|
|
585
|
+
}
|
|
565
586
|
}
|
|
566
587
|
else if (internalValue.length === 1) {
|
|
567
588
|
const selectedId = internalValue[0];
|
|
568
589
|
const selectedItem = state.allOptions.find((opt) => opt.id === selectedId);
|
|
569
590
|
if (selectedItem === null || selectedItem === void 0 ? void 0 : selectedItem.exclusive) {
|
|
570
|
-
|
|
571
|
-
|
|
591
|
+
if (selectedItem.disabled) {
|
|
592
|
+
/* If selected item is disabled and exclusive do not change the selection */
|
|
593
|
+
addItem = false;
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
/* clear the current selection because the old item was exclusive */
|
|
597
|
+
internalValue.pop();
|
|
598
|
+
}
|
|
572
599
|
}
|
|
573
600
|
}
|
|
574
|
-
|
|
575
|
-
|
|
601
|
+
if (addItem) {
|
|
602
|
+
internalValue.push(id);
|
|
603
|
+
hasChanged = true;
|
|
604
|
+
}
|
|
576
605
|
}
|
|
577
606
|
else if (!selected && isAlreadySelected) {
|
|
578
607
|
internalValue.splice(internalValue.indexOf(id), 1);
|
|
@@ -595,6 +624,11 @@ class SelecticStore {
|
|
|
595
624
|
if (id !== oldValue) {
|
|
596
625
|
return hasChanged;
|
|
597
626
|
}
|
|
627
|
+
const oldOption = state.selectedOptions;
|
|
628
|
+
if (oldOption === null || oldOption === void 0 ? void 0 : oldOption.disabled) {
|
|
629
|
+
/* old selection is disabled so do not unselect it */
|
|
630
|
+
return hasChanged;
|
|
631
|
+
}
|
|
598
632
|
id = null;
|
|
599
633
|
}
|
|
600
634
|
else if (id === oldValue) {
|
|
@@ -1364,15 +1398,23 @@ class SelecticStore {
|
|
|
1364
1398
|
if (doNotCheck || !hasFetchedAllItems) {
|
|
1365
1399
|
return;
|
|
1366
1400
|
}
|
|
1401
|
+
const selectedOptions = state.selectedOptions;
|
|
1367
1402
|
const enabledOptions = state.allOptions.filter((opt) => !opt.disabled);
|
|
1368
|
-
const
|
|
1403
|
+
const nbEnabled = enabledOptions.length;
|
|
1369
1404
|
const value = state.internalValue;
|
|
1370
1405
|
const hasValue = Array.isArray(value) ? value.length > 0 : value !== null;
|
|
1371
|
-
const
|
|
1406
|
+
const hasDisabledSelected = Array.isArray(selectedOptions)
|
|
1407
|
+
? selectedOptions.some((opt) => opt.disabled)
|
|
1408
|
+
: false;
|
|
1409
|
+
const hasOnlyValidValue = hasValue && !hasDisabledSelected && (Array.isArray(value) ? value.every((val) => this.hasValue(val)) :
|
|
1372
1410
|
this.hasValue(value));
|
|
1373
|
-
const isEmpty =
|
|
1374
|
-
const hasOnlyOneOption =
|
|
1375
|
-
|
|
1411
|
+
const isEmpty = nbEnabled === 0;
|
|
1412
|
+
const hasOnlyOneOption = nbEnabled === 1 && hasOnlyValidValue && !state.allowClearSelection;
|
|
1413
|
+
const isExclusiveDisabledItem = Array.isArray(selectedOptions) /* which means "multiple" mode */
|
|
1414
|
+
&& selectedOptions.length === 1
|
|
1415
|
+
&& selectedOptions[0].exclusive
|
|
1416
|
+
&& selectedOptions[0].disabled;
|
|
1417
|
+
if (hasOnlyOneOption || isEmpty || isExclusiveDisabledItem) {
|
|
1376
1418
|
if (state.isOpen) {
|
|
1377
1419
|
this.setAutomaticClose();
|
|
1378
1420
|
this.commit('isOpen', false);
|
|
@@ -1792,6 +1834,18 @@ let MainInput = class MainInput extends Vue {
|
|
|
1792
1834
|
? Array.isArray(value) && value.length > 0
|
|
1793
1835
|
: value !== null;
|
|
1794
1836
|
}
|
|
1837
|
+
get disabledList() {
|
|
1838
|
+
const state = this.store.state;
|
|
1839
|
+
const isMultiple = state.multiple;
|
|
1840
|
+
const value = state.selectedOptions;
|
|
1841
|
+
if (!isMultiple || !value) {
|
|
1842
|
+
return [];
|
|
1843
|
+
}
|
|
1844
|
+
const disabledValues = value.filter((option) => {
|
|
1845
|
+
return option.disabled;
|
|
1846
|
+
});
|
|
1847
|
+
return disabledValues;
|
|
1848
|
+
}
|
|
1795
1849
|
get displayPlaceholder() {
|
|
1796
1850
|
const placeholder = this.store.state.placeholder;
|
|
1797
1851
|
const hasValue = this.hasValue;
|
|
@@ -1810,10 +1864,12 @@ let MainInput = class MainInput extends Vue {
|
|
|
1810
1864
|
const state = this.store.state;
|
|
1811
1865
|
const isMultiple = state.multiple;
|
|
1812
1866
|
const value = state.internalValue;
|
|
1813
|
-
const
|
|
1867
|
+
const nbSelection = (Array.isArray(value) && value.length) || 0;
|
|
1868
|
+
const hasOnlyOneValue = nbSelection === 1;
|
|
1869
|
+
const hasOnlyDisabled = nbSelection <= this.disabledList.length;
|
|
1814
1870
|
/* Should not display the clear action if there is only one selected
|
|
1815
1871
|
* item in multiple (as this item has already its remove icon) */
|
|
1816
|
-
return !isMultiple || !hasOnlyOneValue;
|
|
1872
|
+
return !isMultiple || !hasOnlyOneValue || !hasOnlyDisabled;
|
|
1817
1873
|
}
|
|
1818
1874
|
get clearedLabel() {
|
|
1819
1875
|
const isMultiple = this.store.state.multiple;
|
|
@@ -1931,6 +1987,9 @@ let MainInput = class MainInput extends Vue {
|
|
|
1931
1987
|
/* Check if there is enough space to display items like there are
|
|
1932
1988
|
* currently shown */
|
|
1933
1989
|
const el = this.$refs.selectedItems;
|
|
1990
|
+
if (!el) {
|
|
1991
|
+
return;
|
|
1992
|
+
}
|
|
1934
1993
|
const parentEl = el.parentElement;
|
|
1935
1994
|
if (!document.contains(parentEl)) {
|
|
1936
1995
|
/* The element is currently not in DOM */
|
|
@@ -2029,7 +2088,7 @@ let MainInput = class MainInput extends Vue {
|
|
|
2029
2088
|
click: () => this.$emit('item:click', item.id),
|
|
2030
2089
|
} },
|
|
2031
2090
|
h("span", { class: "selectic-input__selected-items__value" }, item.text),
|
|
2032
|
-
!this.isDisabled && (h(Icon$1, { icon: "times", class: "selectic-input__selected-items__icon", store: this.store, on: {
|
|
2091
|
+
!this.isDisabled && !item.disabled && (h(Icon$1, { icon: "times", class: "selectic-input__selected-items__icon", store: this.store, on: {
|
|
2033
2092
|
'click.prevent.stop': () => this.selectItem(item.id),
|
|
2034
2093
|
} }))))),
|
|
2035
2094
|
this.moreSelectedNb && (h("div", { class: "single-value more-items", title: this.moreSelectedTitle }, this.moreSelectedNb)))),
|
|
@@ -2503,42 +2562,6 @@ let ExtendedList = class ExtendedList extends Vue {
|
|
|
2503
2562
|
}
|
|
2504
2563
|
return '';
|
|
2505
2564
|
}
|
|
2506
|
-
get onKeyDown() {
|
|
2507
|
-
return (evt) => {
|
|
2508
|
-
const key = evt.key;
|
|
2509
|
-
if (key === 'Escape') {
|
|
2510
|
-
this.store.commit('isOpen', false);
|
|
2511
|
-
}
|
|
2512
|
-
else if (key === 'Enter') {
|
|
2513
|
-
const index = this.store.state.activeItemIdx;
|
|
2514
|
-
if (index !== -1) {
|
|
2515
|
-
const item = this.store.state.filteredOptions[index];
|
|
2516
|
-
if (!item.disabled && !item.isGroup) {
|
|
2517
|
-
this.store.selectItem(item.id);
|
|
2518
|
-
}
|
|
2519
|
-
}
|
|
2520
|
-
evt.stopPropagation();
|
|
2521
|
-
evt.preventDefault();
|
|
2522
|
-
}
|
|
2523
|
-
else if (key === 'ArrowUp') {
|
|
2524
|
-
const index = this.store.state.activeItemIdx;
|
|
2525
|
-
if (index > 0) {
|
|
2526
|
-
this.store.commit('activeItemIdx', index - 1);
|
|
2527
|
-
}
|
|
2528
|
-
evt.stopPropagation();
|
|
2529
|
-
evt.preventDefault();
|
|
2530
|
-
}
|
|
2531
|
-
else if (key === 'ArrowDown') {
|
|
2532
|
-
const index = this.store.state.activeItemIdx;
|
|
2533
|
-
const max = this.store.state.totalFilteredOptions - 1;
|
|
2534
|
-
if (index < max) {
|
|
2535
|
-
this.store.commit('activeItemIdx', index + 1);
|
|
2536
|
-
}
|
|
2537
|
-
evt.stopPropagation();
|
|
2538
|
-
evt.preventDefault();
|
|
2539
|
-
}
|
|
2540
|
-
};
|
|
2541
|
-
}
|
|
2542
2565
|
get bestPosition() {
|
|
2543
2566
|
const windowHeight = window.innerHeight;
|
|
2544
2567
|
const isFullyEstimated = this.isFullyEstimated;
|
|
@@ -2654,6 +2677,40 @@ let ExtendedList = class ExtendedList extends Vue {
|
|
|
2654
2677
|
clickHeaderGroup() {
|
|
2655
2678
|
this.store.selectGroup(this.topGroupId, !this.topGroupSelected);
|
|
2656
2679
|
}
|
|
2680
|
+
onKeyDown(evt) {
|
|
2681
|
+
const key = evt.key;
|
|
2682
|
+
if (key === 'Escape') {
|
|
2683
|
+
this.store.commit('isOpen', false);
|
|
2684
|
+
}
|
|
2685
|
+
else if (key === 'Enter') {
|
|
2686
|
+
const index = this.store.state.activeItemIdx;
|
|
2687
|
+
if (index !== -1) {
|
|
2688
|
+
const item = this.store.state.filteredOptions[index];
|
|
2689
|
+
if (!item.disabled && !item.isGroup) {
|
|
2690
|
+
this.store.selectItem(item.id);
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
evt.stopPropagation();
|
|
2694
|
+
evt.preventDefault();
|
|
2695
|
+
}
|
|
2696
|
+
else if (key === 'ArrowUp') {
|
|
2697
|
+
const index = this.store.state.activeItemIdx;
|
|
2698
|
+
if (index > 0) {
|
|
2699
|
+
this.store.commit('activeItemIdx', index - 1);
|
|
2700
|
+
}
|
|
2701
|
+
evt.stopPropagation();
|
|
2702
|
+
evt.preventDefault();
|
|
2703
|
+
}
|
|
2704
|
+
else if (key === 'ArrowDown') {
|
|
2705
|
+
const index = this.store.state.activeItemIdx;
|
|
2706
|
+
const max = this.store.state.totalFilteredOptions - 1;
|
|
2707
|
+
if (index < max) {
|
|
2708
|
+
this.store.commit('activeItemIdx', index + 1);
|
|
2709
|
+
}
|
|
2710
|
+
evt.stopPropagation();
|
|
2711
|
+
evt.preventDefault();
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2657
2714
|
/* }}} */
|
|
2658
2715
|
/* {{{ Life cycles */
|
|
2659
2716
|
mounted() {
|
|
@@ -2783,7 +2840,8 @@ let Selectic = class Selectic extends Vue {
|
|
|
2783
2840
|
const store = this.store;
|
|
2784
2841
|
const keepOpenWithOtherSelectic = this.params.keepOpenWithOtherSelectic;
|
|
2785
2842
|
const extendedList = this.$refs.extendedList;
|
|
2786
|
-
|
|
2843
|
+
const extendedListEl = extendedList === null || extendedList === void 0 ? void 0 : extendedList.$el;
|
|
2844
|
+
if (!extendedListEl) {
|
|
2787
2845
|
/* this component is not focused anymore */
|
|
2788
2846
|
if (!keepOpenWithOtherSelectic) {
|
|
2789
2847
|
this.removeListeners();
|
|
@@ -2792,7 +2850,7 @@ let Selectic = class Selectic extends Vue {
|
|
|
2792
2850
|
return;
|
|
2793
2851
|
}
|
|
2794
2852
|
const target = evt.target;
|
|
2795
|
-
if (!
|
|
2853
|
+
if (!extendedListEl.contains(target) && !this.$el.contains(target)) {
|
|
2796
2854
|
store.commit('isOpen', false);
|
|
2797
2855
|
}
|
|
2798
2856
|
};
|
|
@@ -2885,14 +2943,23 @@ let Selectic = class Selectic extends Vue {
|
|
|
2885
2943
|
/* }}} */
|
|
2886
2944
|
/* {{{ private methods */
|
|
2887
2945
|
computeWidth() {
|
|
2888
|
-
|
|
2889
|
-
|
|
2946
|
+
var _a;
|
|
2947
|
+
const mainInput = (_a = this.$refs) === null || _a === void 0 ? void 0 : _a.mainInput;
|
|
2948
|
+
const mainEl = mainInput === null || mainInput === void 0 ? void 0 : mainInput.$el;
|
|
2949
|
+
if (!mainEl) {
|
|
2950
|
+
/* This method has been called too soon (before render function)
|
|
2951
|
+
* or too late (after unmount) */
|
|
2952
|
+
return;
|
|
2953
|
+
}
|
|
2954
|
+
this.width = mainEl.offsetWidth;
|
|
2890
2955
|
}
|
|
2891
2956
|
computeOffset(doNotAddListener = false) {
|
|
2892
|
-
|
|
2957
|
+
var _a;
|
|
2958
|
+
const mainInput = (_a = this.$refs) === null || _a === void 0 ? void 0 : _a.mainInput;
|
|
2893
2959
|
const mainEl = mainInput === null || mainInput === void 0 ? void 0 : mainInput.$el;
|
|
2894
2960
|
if (!mainEl) {
|
|
2895
|
-
/* This method has been called too soon (before render function)
|
|
2961
|
+
/* This method has been called too soon (before render function)
|
|
2962
|
+
* or too late (after unmount) */
|
|
2896
2963
|
return;
|
|
2897
2964
|
}
|
|
2898
2965
|
const _elementsListeners = this._elementsListeners;
|
|
@@ -3026,13 +3093,14 @@ let Selectic = class Selectic extends Vue {
|
|
|
3026
3093
|
checkFocus() {
|
|
3027
3094
|
/* Await that focused element becomes active */
|
|
3028
3095
|
setTimeout(() => {
|
|
3096
|
+
var _a;
|
|
3029
3097
|
const focusedEl = document.activeElement;
|
|
3030
|
-
const extendedList = this.$refs.extendedList;
|
|
3098
|
+
const extendedList = (_a = this.$refs) === null || _a === void 0 ? void 0 : _a.extendedList;
|
|
3031
3099
|
/* check if there is a focused element (if none the body is
|
|
3032
3100
|
* selected) and if it is inside current Selectic */
|
|
3033
3101
|
if (focusedEl === document.body
|
|
3034
3102
|
|| this.$el.contains(focusedEl)
|
|
3035
|
-
|| (extendedList
|
|
3103
|
+
|| (extendedList === null || extendedList === void 0 ? void 0 : extendedList.$el.contains(focusedEl))) {
|
|
3036
3104
|
return;
|
|
3037
3105
|
}
|
|
3038
3106
|
this.store.commit('isOpen', false);
|
package/doc/list.md
CHANGED
|
@@ -28,12 +28,13 @@ It is possible to define the `option` more precisely.
|
|
|
28
28
|
* **text** {`string`} _(mandatory)_: The text which is displayed to select the option or when it is selected.
|
|
29
29
|
* **title** {`string`}: Text displayed in `title` when cursor is over the option (default: `''`).
|
|
30
30
|
* **disabled** {`boolean`}: if `true`, this option cannot be selected (default: `false`).
|
|
31
|
+
In "multiple" mode, if the option is already selected, it cannot be removed from selection (it can always be removed by changing `value` of the component).
|
|
31
32
|
* **className** {`string`}: `class` that are applied on the option (default: `''`).
|
|
32
33
|
* **style** {`string`}: css style which are applied on the option (default: `''`).
|
|
33
34
|
* **icon** {`string`}: class names which are applied on a `<span>` before text in the option to display an icon (default: `''`).
|
|
34
35
|
* **options** {`options[]`}: an other list of options. The current option is considered as a group (equivalent of `optgroup`) (default: `undefined`).
|
|
35
36
|
* **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`).
|
|
36
|
-
* **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.
|
|
37
|
+
* **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.
|
|
37
38
|
* **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`).
|
|
38
39
|
|
|
39
40
|
```javascript
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "selectic",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"description": "Smart Select for VueJS 3.x",
|
|
5
5
|
"main": "dist/selectic.common.js",
|
|
6
6
|
"module": "dist/selectic.esm.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"homepage": "https://github.com/intersec/selectic#readme",
|
|
18
18
|
"keywords": [
|
|
19
19
|
"select",
|
|
20
|
+
"selectic",
|
|
20
21
|
"multiselect",
|
|
21
22
|
"multi-select",
|
|
22
23
|
"multi-select",
|
package/src/ExtendedList.tsx
CHANGED
|
@@ -97,48 +97,6 @@ export default class ExtendedList extends Vue<Props> {
|
|
|
97
97
|
return '';
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
get onKeyDown() {
|
|
101
|
-
return (evt: KeyboardEvent) => {
|
|
102
|
-
const key = evt.key;
|
|
103
|
-
|
|
104
|
-
if (key === 'Escape') {
|
|
105
|
-
this.store.commit('isOpen', false);
|
|
106
|
-
} else
|
|
107
|
-
if (key === 'Enter') {
|
|
108
|
-
const index = this.store.state.activeItemIdx;
|
|
109
|
-
|
|
110
|
-
if (index !== -1) {
|
|
111
|
-
const item = this.store.state.filteredOptions[index];
|
|
112
|
-
|
|
113
|
-
if (!item.disabled && !item.isGroup) {
|
|
114
|
-
this.store.selectItem(item.id);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
evt.stopPropagation();
|
|
118
|
-
evt.preventDefault();
|
|
119
|
-
} else
|
|
120
|
-
if (key === 'ArrowUp') {
|
|
121
|
-
const index = this.store.state.activeItemIdx;
|
|
122
|
-
|
|
123
|
-
if (index > 0) {
|
|
124
|
-
this.store.commit('activeItemIdx', index - 1);
|
|
125
|
-
}
|
|
126
|
-
evt.stopPropagation();
|
|
127
|
-
evt.preventDefault();
|
|
128
|
-
} else
|
|
129
|
-
if (key === 'ArrowDown') {
|
|
130
|
-
const index = this.store.state.activeItemIdx;
|
|
131
|
-
const max = this.store.state.totalFilteredOptions - 1;
|
|
132
|
-
|
|
133
|
-
if (index < max) {
|
|
134
|
-
this.store.commit('activeItemIdx', index + 1);
|
|
135
|
-
}
|
|
136
|
-
evt.stopPropagation();
|
|
137
|
-
evt.preventDefault();
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
100
|
get bestPosition(): 'top' | 'bottom' {
|
|
143
101
|
const windowHeight = window.innerHeight;
|
|
144
102
|
const isFullyEstimated = this.isFullyEstimated;
|
|
@@ -288,6 +246,46 @@ export default class ExtendedList extends Vue<Props> {
|
|
|
288
246
|
this.store.selectGroup(this.topGroupId, !this.topGroupSelected);
|
|
289
247
|
}
|
|
290
248
|
|
|
249
|
+
private onKeyDown(evt: KeyboardEvent) {
|
|
250
|
+
const key = evt.key;
|
|
251
|
+
|
|
252
|
+
if (key === 'Escape') {
|
|
253
|
+
this.store.commit('isOpen', false);
|
|
254
|
+
} else
|
|
255
|
+
if (key === 'Enter') {
|
|
256
|
+
const index = this.store.state.activeItemIdx;
|
|
257
|
+
|
|
258
|
+
if (index !== -1) {
|
|
259
|
+
const item = this.store.state.filteredOptions[index];
|
|
260
|
+
|
|
261
|
+
if (!item.disabled && !item.isGroup) {
|
|
262
|
+
this.store.selectItem(item.id);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
evt.stopPropagation();
|
|
266
|
+
evt.preventDefault();
|
|
267
|
+
} else
|
|
268
|
+
if (key === 'ArrowUp') {
|
|
269
|
+
const index = this.store.state.activeItemIdx;
|
|
270
|
+
|
|
271
|
+
if (index > 0) {
|
|
272
|
+
this.store.commit('activeItemIdx', index - 1);
|
|
273
|
+
}
|
|
274
|
+
evt.stopPropagation();
|
|
275
|
+
evt.preventDefault();
|
|
276
|
+
} else
|
|
277
|
+
if (key === 'ArrowDown') {
|
|
278
|
+
const index = this.store.state.activeItemIdx;
|
|
279
|
+
const max = this.store.state.totalFilteredOptions - 1;
|
|
280
|
+
|
|
281
|
+
if (index < max) {
|
|
282
|
+
this.store.commit('activeItemIdx', index + 1);
|
|
283
|
+
}
|
|
284
|
+
evt.stopPropagation();
|
|
285
|
+
evt.preventDefault();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
291
289
|
/* }}} */
|
|
292
290
|
/* {{{ Life cycles */
|
|
293
291
|
|
package/src/MainInput.tsx
CHANGED
|
@@ -17,7 +17,7 @@ export interface Props {
|
|
|
17
17
|
@Component
|
|
18
18
|
export default class MainInput extends Vue<Props> {
|
|
19
19
|
public $refs: {
|
|
20
|
-
selectedItems
|
|
20
|
+
selectedItems?: HTMLDivElement;
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/* {{{ props */
|
|
@@ -53,6 +53,22 @@ export default class MainInput extends Vue<Props> {
|
|
|
53
53
|
: value !== null;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
get disabledList(): OptionItem[] {
|
|
57
|
+
const state = this.store.state;
|
|
58
|
+
const isMultiple = state.multiple;
|
|
59
|
+
const value = state.selectedOptions;
|
|
60
|
+
|
|
61
|
+
if (!isMultiple || !value) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const disabledValues = (value as OptionItem[]).filter((option) => {
|
|
66
|
+
return option.disabled;
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return disabledValues;
|
|
70
|
+
}
|
|
71
|
+
|
|
56
72
|
get displayPlaceholder(): boolean {
|
|
57
73
|
const placeholder = this.store.state.placeholder;
|
|
58
74
|
const hasValue = this.hasValue;
|
|
@@ -76,11 +92,13 @@ export default class MainInput extends Vue<Props> {
|
|
|
76
92
|
const state = this.store.state;
|
|
77
93
|
const isMultiple = state.multiple;
|
|
78
94
|
const value = state.internalValue;
|
|
79
|
-
const
|
|
95
|
+
const nbSelection = (Array.isArray(value) && value.length) || 0;
|
|
96
|
+
const hasOnlyOneValue = nbSelection === 1;
|
|
97
|
+
const hasOnlyDisabled = nbSelection <= this.disabledList.length;
|
|
80
98
|
|
|
81
99
|
/* Should not display the clear action if there is only one selected
|
|
82
100
|
* item in multiple (as this item has already its remove icon) */
|
|
83
|
-
return !isMultiple || !hasOnlyOneValue;
|
|
101
|
+
return !isMultiple || !hasOnlyOneValue || !hasOnlyDisabled;
|
|
84
102
|
}
|
|
85
103
|
|
|
86
104
|
get clearedLabel(): string {
|
|
@@ -239,6 +257,11 @@ export default class MainInput extends Vue<Props> {
|
|
|
239
257
|
/* Check if there is enough space to display items like there are
|
|
240
258
|
* currently shown */
|
|
241
259
|
const el = this.$refs.selectedItems;
|
|
260
|
+
|
|
261
|
+
if (!el) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
242
265
|
const parentEl = el.parentElement as HTMLDivElement;
|
|
243
266
|
|
|
244
267
|
if (!document.contains(parentEl)) {
|
|
@@ -401,7 +424,7 @@ export default class MainInput extends Vue<Props> {
|
|
|
401
424
|
>
|
|
402
425
|
{ item.text }
|
|
403
426
|
</span>
|
|
404
|
-
{!this.isDisabled && (
|
|
427
|
+
{!this.isDisabled && !item.disabled && (
|
|
405
428
|
<Icon
|
|
406
429
|
icon="times"
|
|
407
430
|
class="selectic-input__selected-items__icon"
|