UNPKG

@limetech/lime-elements

Version:
116 lines (115 loc) 4.89 kB
import { h } from "@stencil/core"; export class ListRenderer { constructor() { this.defaultConfig = { isOpen: true, badgeIcons: false, }; /** * `aria-orientation` is valid for `listbox` and `radiogroup`, * but not for group (used for checkboxes). * @param role */ this.getAriaOrientation = (role) => { if (role === 'listbox' || role === 'radiogroup') { return 'vertical'; } else { return null; } }; /** * 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) => { var _a; if ('separator' in item) { return (h("li", { class: "mdc-deprecated-list-divider", role: "separator", key: `sep-${index}` }, this.renderTextForSeparator(item), h("div", { class: "limel-list-divider-line" }))); } const attributes = {}; if (index === this.applyTabIndexToItemAtIndex) { attributes.tabindex = '0'; } let itemType; if (this.config.type === 'radio' || this.config.type === 'checkbox') { itemType = this.config.type; } else if (this.config.type === 'selectable') { itemType = 'option'; } else { itemType = 'listitem'; } const key = (_a = item.id) !== null && _a !== void 0 ? _a : `item-${index}`; const classNames = { 'mdc-deprecated-list-item': true, // required for keyboard navigation with arrow keys 'mdc-deprecated-list-item--disabled': !!item.disabled, // MDC’s foundation checks for the disabled class before toggling selected state }; return (h("limel-list-item", Object.assign({ key: key, class: classNames }, attributes, { "data-index": index, type: itemType, text: item.text, secondaryText: item.secondaryText, icon: item.icon, image: item.image, primaryComponent: item.primaryComponent, badgeIcon: this.config.badgeIcons, iconSize: this.config.iconSize, selected: item.selected, disabled: item.disabled, actions: item.actions }))); }; this.renderTextForSeparator = (item) => { if ('text' in item) { return h("h2", { class: "limel-list-divider-title" }, item.text); } }; } render(items, config = {}) { items = items || []; this.config = Object.assign(Object.assign({}, this.defaultConfig), config); let role; switch (this.config.type) { case 'checkbox': { role = 'group'; break; } case 'radio': { role = 'radiogroup'; break; } default: { role = 'listbox'; } } this.applyTabIndexToItemAtIndex = this.getIndexForWhichToApplyTabIndex(items); return (h("ul", { class: "mdc-deprecated-list", role: role, "aria-orientation": this.getAriaOrientation(role) }, items.map(this.renderListItem))); } }