UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

338 lines (331 loc) • 10.5 kB
'use strict'; const dom = require('./dom-117fbac1.js'); const array = require('./array-4fc5abfa.js'); const debounce = require('./debounce-11980960.js'); const index = require('./index-8313e72a.js'); function mutationObserverCallback() { this.setUpItems(); this.setUpFilter(); } const SUPPORTED_ARROW_KEYS = ["ArrowUp", "ArrowDown"]; // -------------------------------------------------------------------------- // // Lifecycle // // -------------------------------------------------------------------------- function initialize() { this.setUpItems(); this.setUpFilter(); this.emitCalciteListChange = debounce.debounce(internalCalciteListChangeEvent.bind(this), 0); } function initializeObserver() { this.observer.observe(this.el, { childList: true, subtree: true }); } function cleanUpObserver() { this.observer.disconnect(); } // -------------------------------------------------------------------------- // // Listeners // // -------------------------------------------------------------------------- function calciteListItemChangeHandler(event) { const { selectedValues } = this; const { item, value, selected, shiftPressed } = event.detail; if (selected) { if (this.multiple && shiftPressed) { this.selectSiblings(item); } if (!this.multiple) { this.deselectSiblingItems(item); } selectedValues.set(value, item); } else { selectedValues.delete(value); if (this.multiple && shiftPressed) { this.selectSiblings(item, true); } } if (!this.multiple) { toggleSingleSelectItemTabbing(item, selected); if (selected) { dom.focusElement(item); } } this.lastSelectedItem = item; this.emitCalciteListChange(); } function calciteListItemValueChangeHandler(event) { event.stopPropagation(); const oldValue = event.detail.oldValue; const selectedValues = this.selectedValues; if (selectedValues.has(oldValue)) { const item = selectedValues.get(oldValue); selectedValues.delete(oldValue); selectedValues.set(event.detail.newValue, item); } } // -------------------------------------------------------------------------- // // Private Methods // // -------------------------------------------------------------------------- function isValidNavigationKey(key) { return !!SUPPORTED_ARROW_KEYS.find((k) => k === key); } function calciteListFocusOutHandler(event) { const { el, items, multiple, selectedValues } = this; if (multiple) { return; } const focusedInside = !!el.contains(event.relatedTarget); if (focusedInside) { toggleSingleSelectItemTabbing(event.target, false); return; } items.forEach((item) => toggleSingleSelectItemTabbing(item, selectedValues.size === 0 ? event.target === item : item.selected)); } function keyDownHandler(event) { const { key, target } = event; if (!isValidNavigationKey(key)) { return; } const { items, multiple, selectionFollowsFocus } = this; const { length: totalItems } = items; const currentIndex = items.indexOf(target); if (!totalItems || currentIndex === -1) { return; } event.preventDefault(); const index = array.getRoundRobinIndex(currentIndex + (key === "ArrowUp" ? -1 : 1), totalItems); const item = items[index]; toggleSingleSelectItemTabbing(item, true); if (!multiple && selectionFollowsFocus) { item.selected = true; } dom.focusElement(item); } function internalCalciteListChangeEvent() { this.calciteListChange.emit(this.selectedValues); } function removeItem(event) { if (event.defaultPrevented) { return; } const item = event.target; const selectedValues = this.selectedValues; if (item.parentElement.tagName === "CALCITE-PICK-LIST-GROUP") { item.parentElement.remove(); Array.from(item.parentElement.children).forEach((item) => selectedValues.delete(item.value)); } else { item.remove(); selectedValues.delete(item.value); } this.emitCalciteListChange(); } function toggleSingleSelectItemTabbing(item, selectable) { // using attribute intentionally if (selectable) { item.removeAttribute("tabindex"); } else { item.setAttribute("tabindex", "-1"); } } async function setFocus(focusId) { if (this.filterEnabled && focusId === "filter") { await dom.focusElement(this.filterEl); return; } const { items, multiple, selectionFollowsFocus } = this; if (items.length === 0) { return; } if (multiple) { return items[0].setFocus(); } const focusTarget = items.find((item) => item.selected) || items[0]; if (selectionFollowsFocus) { focusTarget.selected = true; } return focusTarget.setFocus(); } function setUpItems(tagName) { this.items = Array.from(this.el.querySelectorAll(tagName)); let hasSelected = false; const { items } = this; items.forEach((item) => { item.icon = this.getIconType(); if (!this.multiple) { item.disableDeselect = true; toggleSingleSelectItemTabbing(item, false); } if (item.selected) { hasSelected = true; toggleSingleSelectItemTabbing(item, true); this.selectedValues.set(item.value, item); } }); const [first] = items; if (!hasSelected && first) { toggleSingleSelectItemTabbing(first, true); } } function deselectSiblingItems(item) { this.items.forEach((currentItem) => { if (currentItem.value !== item.value) { currentItem.toggleSelected(false); if (this.selectedValues.has(currentItem.value)) { this.selectedValues.delete(currentItem.value); } } }); } function selectSiblings(item, deselect = false) { if (!this.lastSelectedItem) { return; } const { items } = this; const start = items.findIndex((currentItem) => { return currentItem.value === this.lastSelectedItem.value; }); const end = items.findIndex((currentItem) => { return currentItem.value === item.value; }); items.slice(Math.min(start, end), Math.max(start, end)).forEach((currentItem) => { currentItem.toggleSelected(!deselect); if (!deselect) { this.selectedValues.set(currentItem.value, currentItem); } else { this.selectedValues.delete(currentItem.value); } }); } let groups; function handleFilter(event) { const filteredData = event.detail; const values = filteredData.map((item) => item.value); let hasSelectedMatch = false; if (!groups) { groups = new Set(); } const matchedItems = this.items.filter((item) => { const parent = item.parentElement; const grouped = parent.matches("calcite-pick-list-group"); if (grouped) { groups.add(parent); } const matches = values.includes(item.value); item.hidden = !matches; if (!hasSelectedMatch) { hasSelectedMatch = matches && item.selected; } return matches; }); groups.forEach((group) => { const hasAtLeastOneMatch = matchedItems.some((item) => group.contains(item)); group.hidden = !hasAtLeastOneMatch; if (!hasAtLeastOneMatch) { return; } const parentItem = dom.getSlotted(group, "parent-item"); if (parentItem) { parentItem.hidden = false; if (matchedItems.includes(parentItem)) { Array.from(group.children).forEach((child) => (child.hidden = false)); } } }); groups.clear(); if (matchedItems.length > 0 && !hasSelectedMatch && !this.multiple) { toggleSingleSelectItemTabbing(matchedItems[0], true); } } function getItemData() { return this.items.map((item) => ({ label: item.label, description: item.description, metadata: item.metadata, value: item.value })); } const CSS$1 = { sticky: "sticky" }; exports.ICON_TYPES = void 0; (function (ICON_TYPES) { ICON_TYPES["circle"] = "circle"; ICON_TYPES["square"] = "square"; ICON_TYPES["grip"] = "grip"; })(exports.ICON_TYPES || (exports.ICON_TYPES = {})); var __rest = (undefined && undefined.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; const List = (_a) => { var { props: { disabled, loading, filterEnabled, dataForFilter, handleFilter, filterPlaceholder, el, setFilterEl } } = _a, rest = __rest(_a, ["props"]); const defaultSlot = index.h("slot", null); return (index.h(index.Host, Object.assign({ "aria-busy": loading.toString(), "aria-disabled": disabled.toString(), role: "menu" }, rest), index.h("section", null, index.h("header", { class: { [CSS$1.sticky]: true } }, filterEnabled ? (index.h("calcite-filter", { "aria-label": filterPlaceholder, data: dataForFilter, dir: dom.getElementDir(el), disabled: loading || disabled, onCalciteFilterChange: handleFilter, placeholder: filterPlaceholder, ref: setFilterEl })) : null, index.h("slot", { name: "menu-actions" })), loading || disabled ? index.h("calcite-scrim", { loading: loading }) : null, defaultSlot))); }; const CSS = { actions: "actions", actionsEnd: "actions--end", actionsStart: "actions--start", description: "description", handle: "handle", handleActivated: "handle--activated", highlight: "highlight", icon: "icon", iconDot: "icon-dot", label: "label", remove: "remove", title: "title", textContainer: "text-container" }; const ICONS = { checked: "check", remove: "x" }; const SLOTS = { actionsEnd: "actions-end", actionsStart: "actions-start" }; const TEXT = { remove: "remove" }; exports.CSS = CSS; exports.ICONS = ICONS; exports.List = List; exports.SLOTS = SLOTS; exports.TEXT = TEXT; exports.calciteListFocusOutHandler = calciteListFocusOutHandler; exports.calciteListItemChangeHandler = calciteListItemChangeHandler; exports.calciteListItemValueChangeHandler = calciteListItemValueChangeHandler; exports.cleanUpObserver = cleanUpObserver; exports.deselectSiblingItems = deselectSiblingItems; exports.getItemData = getItemData; exports.handleFilter = handleFilter; exports.initialize = initialize; exports.initializeObserver = initializeObserver; exports.keyDownHandler = keyDownHandler; exports.mutationObserverCallback = mutationObserverCallback; exports.removeItem = removeItem; exports.selectSiblings = selectSiblings; exports.setFocus = setFocus; exports.setUpItems = setUpItems;