Skip to content

Commit 115900b

Browse files
authored
feat(ui5-multi-combobox): initial implementation (#379)
FIXES: #314
1 parent 9e0c9aa commit 115900b

File tree

79 files changed

+1868
-55
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1868
-55
lines changed

packages/base/.eslintrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ module.exports = {
7272
"no-script-url": 2,
7373
"no-self-compare": 2,
7474
"no-sequences": 2,
75-
"no-unused-expressions": 1,
75+
"no-unused-expressions": [1, { allowShortCircuit: true }],
7676
"no-void": 2,
7777
"no-warning-comments": 0,
7878
"no-with": 2,

packages/base/src/delegate/ItemNavigation.js

+4
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ class ItemNavigation extends EventProvider {
169169
_getCurrentItem() {
170170
const items = this._getItems();
171171

172+
if (!items.length) {
173+
return null;
174+
}
175+
172176
// normalize the index
173177
while (this.currentIndex >= items.length) {
174178
this.currentIndex -= this.rowSize;

packages/base/src/events/PseudoEvents.js

+15
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ const isTabNext = event => (event.key ? event.key === "Tab" : event.keyCode ===
2222

2323
const isTabPrevious = event => (event.key ? event.key === "Tab" : event.keyCode === KeyCodes.TAB) && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ false, /* Shift */ true);
2424

25+
const isBackSpace = event => (event.key ? (event.key === "Backspace" || event.key === "Backspace") : event.keyCode === KeyCodes.BACKSPACE) && !hasModifierKeys(event);
26+
27+
const isDelete = event => (event.key ? (event.key === "Delete" || event.key === "Delete") : event.keyCode === KeyCodes.DELETE) && !hasModifierKeys(event);
28+
29+
const isShow = event => {
30+
if (event.key) {
31+
return (event.key === "F4" && !hasModifierKeys(event)) || ((event.key === "ArrowDown" || event.key === "Down") && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ true, /* Shift */ false));
32+
}
33+
34+
return (event.keyCode === KeyCodes.F4 && !hasModifierKeys(event)) || (event.keyCode === KeyCodes.ARROW_DOWN && checkModifierKeys(event, /* Ctrl */ false, /* Alt */ true, /* Shift */ false));
35+
};
36+
2537
const hasModifierKeys = event => event.shiftKey || event.altKey || getCtrlKey(event);
2638

2739
const getCtrlKey = event => !!(event.metaKey || event.ctrlKey); // double negation doesn't have effect on boolean but ensures null and undefined are equivalent to false.
@@ -40,4 +52,7 @@ export {
4052
isEscape,
4153
isTabNext,
4254
isTabPrevious,
55+
isBackSpace,
56+
isDelete,
57+
isShow,
4358
};

packages/main/.eslintrc.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ module.exports = {
7272
"no-script-url": 2,
7373
"no-self-compare": 2,
7474
"no-sequences": 2,
75-
"no-unused-expressions": 1,
75+
"no-unused-expressions": [1, { allowShortCircuit: true }],
7676
"no-void": 2,
7777
"no-warning-comments": 1,
7878
"no-with": 2,

packages/main/bundle.esm.js

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import ShellBar from "./dist/ShellBar.js";
3131
import ShellBarItem from "./dist/ShellBarItem.js";
3232
import Switch from "./dist/Switch.js";
3333
import MessageStrip from "./dist/MessageStrip.js";
34+
import MultiComboBox from "./dist/MultiComboBox.js";
3435
import TabContainer from "./dist/TabContainer.js";
3536
import Tab from "./dist/Tab.js";
3637
import TabSeparator from "./dist/TabSeparator.js";
@@ -42,6 +43,8 @@ import TextArea from "./dist/TextArea.js";
4243
import Timeline from "./dist/Timeline.js";
4344
import TimelineItem from "./dist/TimelineItem.js";
4445
import Title from "./dist/Title.js";
46+
import Token from "./dist/Token.js";
47+
import Tokenizer from "./dist/Tokenizer.js";
4548
import ToggleButton from "./dist/ToggleButton.js";
4649

4750
import List from "./dist/List.js";
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
TEXTAREA_CHARACTERS_LEFT
22
TEXTAREA_CHARACTERS_EXCEEDED
3-
PANEL_ICON
3+
PANEL_ICON
4+
MULTIINPUT_SHOW_MORE_TOKENS

packages/main/src/Input.hbs

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
<div id="{{ctr._id}}-wrapper"
88
class="{{classes.wrapper}}"
99
>
10+
{{#if ctr._beginContent}}
11+
<slot name="_beginContent"></slot>
12+
{{/if}}
13+
1014
<input id="{{ctr._id}}-inner"
1115
class="sapWCInputBaseInner"
1216
type="{{type}}"

packages/main/src/Input.js

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/src/UI5Element.js";
22
import Bootstrap from "@ui5/webcomponents-base/src/Bootstrap.js";
33
import { isIE } from "@ui5/webcomponents-core/dist/sap/ui/Device.js";
44
import ValueState from "@ui5/webcomponents-base/src/types/ValueState.js";
5+
56
import {
67
isUp,
78
isDown,
@@ -61,6 +62,10 @@ const metadata = {
6162
type: HTMLElement,
6263
multiple: true,
6364
},
65+
66+
_beginContent: {
67+
type: HTMLElement,
68+
},
6469
},
6570
properties: /** @lends sap.ui.webcomponents.main.Input.prototype */ {
6671

packages/main/src/MultiComboBox.hbs

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<div class="ui5-multi-combobox--wrapper">
2+
<ui5-input id="ui5-multi-combobox--input"
3+
value="{{ctr.value}}"
4+
placeholder="{{ctr.placeholder}}"
5+
?disabled={{ctr.disabled}}
6+
?readonly={{ctr.readonly}}
7+
value-state="{{ctr.valueState}}"
8+
show-suggestions
9+
@ui5-input="{{ctr._inputLiveChange}}"
10+
@ui5-change={{ctr._inputChange}}
11+
@keydown="{{ctr._keydown}}">
12+
13+
<ui5-tokenizer slot="_beginContent"
14+
show-more
15+
class="ui5-multi-combobox-tokenizer"
16+
?disabled="{{ctr.disabled}}"
17+
@ui5-showMoreItemsPress="{{ctr._showMorePopover}}"
18+
@ui5-tokenDelete="{{ctr._tokenDelete}}"
19+
@focusout="{{ctr._tokenizerFocusOut}}"
20+
>
21+
{{#each ctr.items}}
22+
{{#if this.selected}}
23+
<ui5-token ?readonly="{{../../ctr.readonly}}" class="ui5-multi-combobox--token" data-ui5-id="{{this._id}}" >{{this.textContent}}</ui5-token>
24+
{{/if}}
25+
{{/each}}
26+
</ui5-tokenizer>
27+
28+
{{#unless ctr.readonly}}
29+
<ui5-icon src="sap-icon://slim-arrow-down"
30+
slot="icon"
31+
@ui5-press={{ctr._showAllItemsPopover}}
32+
class="{{classes.icon}}"
33+
></ui5-icon>
34+
{{/unless}}
35+
</ui5-input>
36+
37+
<ui5-popover
38+
class="ui5-multi-combobox-selected-items--popover"
39+
horizontal-align="Stretch"
40+
hide-header
41+
?hide-arrow={{editable}}
42+
placement-type="Bottom">
43+
<ui5-list separators="None" mode="{{selectedItemsListMode}}"
44+
@ui5-selectionChange={{ctr._selectedItemsSelectionChange}}>
45+
{{#each ctr.items}}
46+
{{#if this.selected}}
47+
<ui5-li type="Active" data-ui5-token-id="{{this._id}}" .selected="{{../../editable}}">{{this.textContent}}</ui5-li>
48+
{{/if}}
49+
{{/each}}
50+
</ui5-list>
51+
</ui5-popover>
52+
53+
<ui5-popover class="ui5-multi-combobox-all-items--popover"
54+
hide-header
55+
hide-arrow
56+
horizontal-align="Stretch"
57+
initial-focus="ui5-multi-combobox--input"
58+
horizontal-align="Left"
59+
placement-type="Bottom"
60+
@ui5-selectionChange={{ctr._allItemsSelectionChange}}
61+
@ui5-afterClose={{ctr._afterAllPopoverClose}}
62+
@ui5-afterOpen={{ctr._afterAllPopoverOpen}}>
63+
<ui5-list separators="None" mode="MultiSelect" class="ui5-multi-combobox-all-items-list">
64+
{{#each ctr._filteredItems}}
65+
<ui5-li type="Active" ?selected={{this.selected}} data-ui5-token-id="{{this._id}}">{{this.textContent}}</ui5-li>
66+
{{/each}}
67+
</ui5-list>
68+
</ui5-popover>
69+
70+
</div>

0 commit comments

Comments
 (0)