Skip to content

Commit

Permalink
feat(ui5-combobox/multi-combobox): physical items
Browse files Browse the repository at this point in the history
  • Loading branch information
MapTo0 committed Oct 18, 2024
1 parent 95db5c6 commit fd493ae
Show file tree
Hide file tree
Showing 18 changed files with 466 additions and 482 deletions.
29 changes: 10 additions & 19 deletions packages/main/src/ComboBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,13 @@ interface IComboBoxItem extends UI5Element {
isGroupItem?: boolean,
selected?: boolean,
additionalText?: string,
stableDomRef: string,
_isVisible?: boolean,
items?: Array<IComboBoxItem>
}

type ValueStateAnnouncement = Record<Exclude<ValueState, ValueState.None>, string>;
type ValueStateTypeAnnouncement = Record<Exclude<ValueState, ValueState.None>, string>;

type ComboBoxListItem = ListItemStandard & {
mappedItem: ComboBoxItem
};

enum ValueStateIconMapping {
Negative = "error",
Critical = "alert",
Expand Down Expand Up @@ -398,7 +393,12 @@ class ComboBox extends UI5Element implements IFormInputElement {
* Defines the component items.
* @public
*/
@slot({ type: HTMLElement, "default": true, invalidateOnChildChange: true })
@slot({
type: HTMLElement,
"default": true,
individualSlots: true,
invalidateOnChildChange: true,
})
items!: Array<IComboBoxItem>;

/**
Expand Down Expand Up @@ -504,10 +504,6 @@ class ComboBox extends UI5Element implements IFormInputElement {
}

this.storeResponsivePopoverWidth();

this.items.forEach(item => {
item._getRealDomRef = () => this._getPicker().querySelector(`*[data-ui5-stable=${item.stableDomRef}]`)!;
});
}

_focusin(e: FocusEvent) {
Expand Down Expand Up @@ -1129,9 +1125,9 @@ class ComboBox extends UI5Element implements IFormInputElement {
}

_selectItem(e: CustomEvent<ListItemClickEventDetail>) {
const listItem = e.detail.item as ComboBoxListItem;
const item = e.detail.item as ComboBoxItem;

this._selectedItemText = listItem.mappedItem.text || "";
this._selectedItemText = item.text || "";
this._selectionPerformed = true;

const sameItemSelected = this.value === this._selectedItemText;
Expand All @@ -1144,17 +1140,12 @@ class ComboBox extends UI5Element implements IFormInputElement {

this.value = this._selectedItemText;

if (!listItem.mappedItem.selected) {
if (!item.selected) {
this.fireDecoratorEvent<ComboBoxSelectionChangeEventDetail>("selection-change", {
item: listItem.mappedItem,
item,
});
}

this._filteredItems.map(item => {
item.selected = (item === listItem.mappedItem && !item.isGroupItem);
return item;
});

this._fireChangeEvent();
this._closeRespPopover();

Expand Down
14 changes: 14 additions & 0 deletions packages/main/src/ComboBoxItem.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{{>include "./ListItemBase.hbs"}}

{{#*inline "listItemContent"}}
<div part="content" id="content" class="ui5-li-content">
<div class="ui5-li-text-wrapper">
<span part="title" class="ui5-li-title">
{{{text}}}
</span>
{{#if additionalText}}
<span part="additional-text" class="ui5-li-additional-text">{{additionalText}}</span>
{{/if}}
</div>
</div>
{{/inline}}
26 changes: 21 additions & 5 deletions packages/main/src/ComboBoxItem.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import type { IComboBoxItem } from "./ComboBox.js";
import ListItemBase from "./ListItemBase.js";

import ComboBoxItemTemplate from "./generated/templates/ComboBoxItemTemplate.lit.js";
/**
* @class
* The `ui5-cb-item` represents the item for a `ui5-combobox`.
Expand All @@ -12,8 +13,12 @@ import type { IComboBoxItem } from "./ComboBox.js";
* @implements {IComboBoxItem}
* @public
*/
@customElement("ui5-cb-item")
class ComboBoxItem extends UI5Element implements IComboBoxItem {
@customElement({
tag: "ui5-cb-item",
template: ComboBoxItemTemplate,
styles: [ListItemBase.styles],
})
class ComboBoxItem extends ListItemBase implements IComboBoxItem {
/**
* Defines the text of the component.
* @default undefined
Expand Down Expand Up @@ -52,8 +57,19 @@ class ComboBoxItem extends UI5Element implements IComboBoxItem {
@property({ type: Boolean })
selected = false;

get stableDomRef() {
return this.getAttribute("stable-dom-ref") || `${this._id}-stable-dom-ref`;
/**
* Defines the markup text that will be displayed as suggestion.
* Used for highlighting the matching parts of the text.
*
* @since 2.0.0
* @private
*/
@property()
markupText = "";

onEnterDOM(): void {
super.onEnterDOM();
this.setAttribute("accessible-role", "Option");
}
}

Expand Down
9 changes: 9 additions & 0 deletions packages/main/src/ComboBoxItemGroup.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{>include "./ListItemGroup.hbs"}}

{{#*inline "items"}}
{{#each items}}
{{#if _isVisible}}
<slot name="{{this._individualSlot}}"></slot>
{{/if}}
{{/each}}
{{/inline}}
72 changes: 27 additions & 45 deletions packages/main/src/ComboBoxItemGroup.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import type { IComboBoxItem } from "./ComboBox.js";
import ListItemGroup from "./ListItemGroup.js";
import type ComboBoxItem from "./ComboBoxItem.js";
import ComboBoxItemGroupTemplate from "./generated/templates/ComboBoxItemGroupTemplate.lit.js";

/**
* @class
Expand All @@ -15,49 +16,30 @@ import type { IComboBoxItem } from "./ComboBox.js";
* @implements {IComboBoxItem}
* @since 1.0.0-rc.15
*/
@customElement("ui5-cb-item-group")
class ComboBoxItemGroup extends UI5Element implements IComboBoxItem {
/**
* Defines the text of the component.
* @default undefined
* @public
*/
@property()
headerText?: string;

/**
* Indicates whether the item is focused
* @protected
*/
@property({ type: Boolean })
focused = false

/**
* Defines the items of the <code>ui5-cb-item-group</code>.
* @public
*/
@slot({
"default": true,
invalidateOnChildChange: true,
type: HTMLElement,
})
items!: Array<IComboBoxItem>;

/**
* Used to avoid tag name checks
* @protected
*/
get isGroupItem(): boolean {
return true;
}

get stableDomRef() {
return this.getAttribute("stable-dom-ref") || `${this._id}-stable-dom-ref`;
}

get _isVisible() {
return this.items.some(item => item._isVisible);
}
@customElement({
tag: "ui5-cb-item-group",
template: ComboBoxItemGroupTemplate,
})
class ComboBoxItemGroup extends ListItemGroup implements IComboBoxItem {
/**
* Defines the items of the <code>ui5-cb-item-group</code>.
* @public
*/
@slot({
"default": true,
invalidateOnChildChange: true,
individualSlots: true,
type: HTMLElement,
})
items!: Array<ComboBoxItem>;

get isGroupItem(): boolean {
return true;
}

get _isVisible() {
return this.items.some(item => item._isVisible);
}
}

ComboBoxItemGroup.define();
Expand Down
33 changes: 2 additions & 31 deletions packages/main/src/ComboBoxPopover.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,7 @@
selection-mode="Single"
>
{{#each _filteredItems}}
{{#if isGroupItem}}
{{#if _isVisible}}
<ui5-li-group header-text="{{this.headerText}}" ?focused={{this.focused}}>
{{#each this.items}}
{{#if _isVisible}}
{{> listItem}}
{{/if}}
{{/each}}
</ui5-li-group>
{{/if}}
{{else}}
{{> listItem}}
{{/if}}

<slot name="{{this._individualSlot}}"></slot>
{{/each}}
</ui5-list>

Expand Down Expand Up @@ -140,20 +127,4 @@
{{else}}
<slot name="valueStateMessage"></slot>
{{/if}}
{{/inline}}

{{#*inline "listItem"}}
<ui5-li
accessible-role="Option"
type="Active"
wrapping-type="Normal"
additional-text={{this.additionalText}}
group-name={{this.groupName}}
.mappedItem={{this}}
?selected={{this.selected}}
?focused={{this.focused}}
data-ui5-stable="{{this.stableDomRef}}"
>
{{this.text}}
</ui5-li>
{{/inline}}
{{/inline}}
4 changes: 2 additions & 2 deletions packages/main/src/List.ts
Original file line number Diff line number Diff line change
Expand Up @@ -873,10 +873,10 @@ class List extends UI5Element {

slottedItems.forEach(item => {
if (isInstanceOfListItemGroup(item)) {
const groupItems = [item.groupHeaderItem, ...item.items].filter(Boolean);
const groupItems = [item.groupHeaderItem, ...item.items.filter(listItem => listItem.assignedSlot)].filter(Boolean);
items.push(...groupItems);
} else {
items.push(item);
item.assignedSlot && items.push(item);
}
});

Expand Down
15 changes: 11 additions & 4 deletions packages/main/src/ListItemGroup.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@
@dragover="{{_ondragover}}"
@drop="{{_ondrop}}"
@dragleave="{{_ondragleave}}">

{{#if hasHeader}}
<ui5-li-group-header ?focused="{{focused}}" part="header">
{{#if hasFormattedHeader}}
<slot name="header"></slot>
<slot name="header"></slot>
{{else}}
{{headerText}}
{{headerText}}
{{/if}}
</ui5-li-group-header>
{{/if}}
<slot></slot>

{{> items}}
<ui5-drop-indicator
orientation="Horizontal"
.ownerReference="{{this}}"
></ui5-drop-indicator>
</ul>
</ul>


{{#*inline "items"}}
<slot></slot>
{{/inline}}
Loading

0 comments on commit fd493ae

Please sign in to comment.