@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
317 lines (311 loc) • 10.1 kB
JavaScript
import { f as focusElement, b as getSlotted, g as getElementDir } from './dom-466af3c7.js';
import { g as getRoundRobinIndex } from './array-af19adb2.js';
import { d as debounce } from './debounce-047e09f4.js';
import { h, H as Host } from './index-aa8afca4.js';
function mutationObserverCallback() {
this.setUpItems();
this.setUpFilter();
}
const SUPPORTED_ARROW_KEYS = ["ArrowUp", "ArrowDown"];
// --------------------------------------------------------------------------
//
// Lifecycle
//
// --------------------------------------------------------------------------
function initialize() {
this.setUpItems();
this.setUpFilter();
this.emitCalciteListChange = 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) {
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 = getRoundRobinIndex(currentIndex + (key === "ArrowUp" ? -1 : 1), totalItems);
const item = items[index];
toggleSingleSelectItemTabbing(item, true);
if (!multiple && selectionFollowsFocus) {
item.selected = true;
}
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 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 = 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"
};
var ICON_TYPES;
(function (ICON_TYPES) {
ICON_TYPES["circle"] = "circle";
ICON_TYPES["square"] = "square";
ICON_TYPES["grip"] = "grip";
})(ICON_TYPES || (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 = h("slot", null);
return (h(Host, Object.assign({ "aria-busy": loading.toString(), "aria-disabled": disabled.toString(), role: "menu" }, rest),
h("section", null,
h("header", { class: { [CSS$1.sticky]: true } },
filterEnabled ? (h("calcite-filter", { "aria-label": filterPlaceholder, data: dataForFilter, dir: getElementDir(el), disabled: loading || disabled, onCalciteFilterChange: handleFilter, placeholder: filterPlaceholder, ref: setFilterEl })) : null,
h("slot", { name: "menu-actions" })),
loading || disabled ? 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"
};
export { CSS as C, ICON_TYPES as I, List as L, SLOTS as S, TEXT as T, initializeObserver as a, calciteListItemChangeHandler as b, cleanUpObserver as c, deselectSiblingItems as d, calciteListItemValueChangeHandler as e, setUpItems as f, getItemData as g, handleFilter as h, initialize as i, setFocus as j, keyDownHandler as k, calciteListFocusOutHandler as l, mutationObserverCallback as m, ICONS as n, removeItem as r, selectSiblings as s };