@limetech/lime-elements
Version:
228 lines (227 loc) • 9.06 kB
JavaScript
import { h } from '@stencil/core';
import { CheckboxTemplate } from '../checkbox/checkbox.template';
import { RadioButtonTemplate } from '../radio-button-group/radio-button.template';
import { getIconColor, getIconName, getIconTitle, } from '../icon/get-icon-props';
import { isEmpty } from 'lodash-es';
export class ListRenderer {
constructor() {
this.defaultConfig = {
isOpen: true,
badgeIcons: false,
};
/**
* Determine which ListItem should have the `tab-index` attribute set,
* and return the index at which that ListItem is located in `items`.
* Returns `undefined` if no item should have the attribute set.
* See https://github.com/material-components/material-components-web/tree/e66a43a75fef4f9179e24856649518e15e279a04/packages/mdc-list#accessibility
*
* @param items - the items of the list, including any `ListSeparator`:s
* @returns the index as per the description
*/
this.getIndexForWhichToApplyTabIndex = (items) => {
let result;
for (let i = 0, max = items.length; i < max; i += 1) {
if ('separator' in items[i]) {
// Ignore ListSeparator
}
else {
const item = items[i];
if (item.disabled) {
// Skip disabled items - they should never get tabindex
continue;
}
if (item.selected) {
result = i;
break;
}
if (result === undefined) {
result = i;
// Do NOT break, as any later item with
// `selected=true` should get the tab-index instead!
}
}
}
return result;
};
/**
* Render a single list item
*
* @param item - the item to render
* @param index - the index the item had in the `items` array
* @returns the list item
*/
this.renderListItem = (item, index) => {
if ('separator' in item) {
return (h("li", { class: "mdc-deprecated-list-divider", role: "separator" }, this.renderTextForSeparator(item), h("div", { class: "limel-list-divider-line" })));
}
if (['radio', 'checkbox'].includes(this.config.type)) {
return this.renderVariantListItem(this.config, item, index);
}
const classNames = {
'mdc-deprecated-list-item': true,
'mdc-deprecated-list-item--disabled': item.disabled,
'mdc-deprecated-list-item--selected': item.selected,
'has-primary-component': this.hasPrimaryComponent(item),
};
const attributes = {};
if (index === this.applyTabIndexToItemAtIndex) {
attributes.tabindex = '0';
}
return (h("li", Object.assign({ class: classNames, "aria-disabled": item.disabled ? 'true' : 'false', "aria-selected": item.selected ? 'true' : 'false', "data-index": index }, attributes), this.renderIcon(this.config, item), this.renderPicture(item), this.getPrimaryComponent(item), this.renderText(item), this.twoLines && this.avatarList ? this.renderDivider() : null, this.renderActionMenu(item.actions)));
};
this.renderTextForSeparator = (item) => {
if ('text' in item) {
return h("h2", { class: "limel-list-divider-title" }, item.text);
}
};
this.hasPrimaryComponent = (item) => {
var _a;
return !!((_a = item === null || item === void 0 ? void 0 : item.primaryComponent) === null || _a === void 0 ? void 0 : _a.name);
};
/**
* Render the text of the list item
*
* @param item - the list item
* @returns the text for the list item
*/
this.renderText = (item) => {
if (this.isSimpleItem(item)) {
return (h("span", { class: "mdc-deprecated-list-item__text" }, item.text));
}
return (h("div", { class: "mdc-deprecated-list-item__text" }, h("div", { class: "mdc-deprecated-list-item__primary-command-text" }, h("div", { class: "mdc-deprecated-list-item__primary-text" }, item.text)), h("div", { class: "mdc-deprecated-list-item__secondary-text" }, item.secondaryText)));
};
this.isSimpleItem = (item) => {
return !('secondaryText' in item);
};
/**
* Render an icon for a list item
*
* @param config - the config object, passed on from the `renderListItem` function
* @param item - the list item
* @returns the icon element
*/
this.renderIcon = (config, item) => {
const style = {};
const name = getIconName(item.icon);
if (!name) {
return;
}
const color = getIconColor(item.icon, item.iconColor);
const title = getIconTitle(item.icon);
if (color) {
if (config.badgeIcons) {
style['--icon-background-color'] = color;
}
else {
style.color = color;
}
}
return (h("limel-icon", { badge: config.badgeIcons, class: "mdc-deprecated-list-item__graphic", name: name, style: style, size: config.iconSize, "aria-label": title, "aria-hidden": title ? null : 'true' }));
};
this.renderDivider = () => {
const classes = {
'mdc-deprecated-list-divider': true,
'mdc-deprecated-list-divider--inset': true,
};
if (this.config.iconSize) {
classes[this.config.iconSize] = true;
}
return h("hr", { class: classes });
};
this.renderActionMenu = (actions) => {
if (!actions || actions.length === 0) {
return;
}
return (h("limel-menu", { class: "mdc-deprecated-list-item__meta", items: actions, openDirection: "left-start" }, h("limel-icon-button", { class: "action-menu-trigger", slot: "trigger", icon: "menu_2" })));
};
this.renderVariantListItem = (config, item, index) => {
let itemTemplate;
if (config.type === 'radio') {
itemTemplate = (h(RadioButtonTemplate, { id: `c_${index}`, checked: item.selected, disabled: item.disabled }));
}
else if (config.type === 'checkbox') {
itemTemplate = (h(CheckboxTemplate, { id: `c_${index}`, checked: item.selected, disabled: item.disabled }));
}
const classNames = {
'mdc-deprecated-list-item': true,
'mdc-deprecated-list-item--disabled': item.disabled,
'mdc-deprecated-list-item__text': !item.secondaryText,
'has-primary-component': this.hasPrimaryComponent(item),
};
const attributes = {};
if (index === this.applyTabIndexToItemAtIndex) {
attributes.tabindex = '0';
}
return (h("li", Object.assign({ class: classNames, role: config.type, "aria-checked": item.selected ? 'true' : 'false', "aria-disabled": item.disabled ? 'true' : 'false', "data-index": index }, attributes), this.renderVariantListItemContent(config, item, itemTemplate)));
};
this.renderVariantListItemContent = (config, item, itemTemplate) => {
if (this.hasIcons) {
return [
item.icon ? this.renderIcon(config, item) : null,
this.getPrimaryComponent(item),
this.renderText(item),
h("div", { class: "mdc-deprecated-list-item__meta" }, itemTemplate),
];
}
return [
h("div", { class: "mdc-deprecated-list-item__graphic" }, itemTemplate),
this.getPrimaryComponent(item),
this.renderText(item),
];
};
}
render(items, config = {}) {
items = items || [];
this.config = Object.assign(Object.assign({}, this.defaultConfig), config);
this.twoLines = items.some((item) => {
return 'secondaryText' in item && !!item.secondaryText;
});
this.hasIcons = items.some((item) => {
return 'icon' in item && !!item.icon;
});
this.avatarList = this.config.badgeIcons && this.hasIcons;
const selectableListTypes = ['selectable', 'radio', 'checkbox'];
let role;
switch (this.config.type) {
case 'checkbox': {
role = 'group';
break;
}
case 'radio': {
role = 'radiogroup';
break;
}
default: {
role = 'listbox';
}
}
this.applyTabIndexToItemAtIndex =
this.getIndexForWhichToApplyTabIndex(items);
const classNames = {
'mdc-deprecated-list': true,
'mdc-deprecated-list--two-line': this.twoLines,
selectable: selectableListTypes.includes(this.config.type),
'mdc-deprecated-list--avatar-list': this.avatarList,
'list--compact': this.twoLines &&
this.commandKey &&
['small', 'x-small'].includes(this.config.iconSize),
};
return (h("ul", { class: classNames, role: role, "aria-orientation": "vertical" }, items.map(this.renderListItem)));
}
getPrimaryComponent(item) {
if (!this.hasPrimaryComponent(item)) {
return;
}
const PrimaryComponent = item.primaryComponent.name;
const props = item.primaryComponent.props;
return h(PrimaryComponent, Object.assign({}, props));
}
renderPicture(item) {
const image = item.image;
if (isEmpty(image)) {
return;
}
return h("img", { src: image.src, alt: image.alt, loading: "lazy" });
}
}
//# sourceMappingURL=list-renderer.js.map