@trimble-oss/moduswebcomponents
Version:
Modus Web Components is a modern, accessible UI library built with Stencil JS that provides reusable web components following Trimble's Modus design system. This updated version focuses on improved flexibility, enhanced theming options, comprehensive cust
101 lines (100 loc) • 3.34 kB
JavaScript
/**
* Reorders a list item by swapping it with the adjacent item in the given direction.
*/
export function reorderListItem(items, currentIndex, direction) {
const targetIdx = currentIndex + direction;
if (targetIdx < 0 || targetIdx >= items.length)
return null;
const newItems = [...items];
[newItems[currentIndex], newItems[targetIdx]] = [
newItems[targetIdx],
newItems[currentIndex],
];
return { items: newItems, targetIndex: targetIdx };
}
/**
* Reorders a grid item by removing it from the current position
* and inserting it at the target position.
*/
export function reorderGridItem(items, currentIndex, offset) {
const targetIdx = currentIndex + offset;
if (targetIdx < 0 || targetIdx >= items.length)
return null;
const newItems = [...items];
const [movedItem] = newItems.splice(currentIndex, 1);
newItems.splice(targetIdx, 0, movedItem);
return { items: newItems, targetIndex: targetIdx };
}
/**
* Calculates the number of columns in the grid layout
* by comparing offsetTop values of consecutive items.
*/
export function getGridColumnCount(el) {
const items = el.querySelectorAll('.modus-wc-app-menu-grid-item');
if (items.length <= 1)
return 1;
const firstTop = items[0].offsetTop;
let count = 1;
for (let i = 1; i < items.length; i++) {
if (items[i].offsetTop === firstTop) {
count++;
}
else {
break;
}
}
return count;
}
/**
* Returns the navigation offset for an arrow key based on the layout.
* Returns null if the key is not applicable for the current layout.
*/
export function getNavigationOffset(key, layout, gridColumnCount) {
switch (key) {
case 'ArrowUp':
return layout === 'grid' ? -gridColumnCount : -1;
case 'ArrowDown':
return layout === 'grid' ? gridColumnCount : 1;
case 'ArrowLeft':
return layout === 'grid' ? -1 : null;
case 'ArrowRight':
return layout === 'grid' ? 1 : null;
default:
return null;
}
}
/**
* Returns the valid target index for focus navigation,
* or null if the target is out of bounds.
*/
export function getTargetFocusIndex(currentIndex, offset, totalItems) {
const targetIdx = currentIndex + offset;
return targetIdx >= 0 && targetIdx < totalItems ? targetIdx : null;
}
/**
* Focuses the app menu item at the given index based on the layout.
*
* In list layout the focus target depends on edit mode: the wrapper row
* (tabIndex 0 in edit mode) or the inner `<li>` rendered by
* modus-wc-menu-item (native tab stop in normal mode).
*/
export function focusAppMenuItem(el, layout, appIndex) {
var _a;
if (layout === 'grid') {
const items = el.querySelectorAll('.modus-wc-app-menu-grid-item');
(_a = items[appIndex]) === null || _a === void 0 ? void 0 : _a.focus();
}
else {
const rows = el.querySelectorAll('.modus-wc-app-menu-item-row');
const row = rows[appIndex];
if (!row)
return;
if (row.tabIndex === 0) {
row.focus();
}
else {
const li = row.querySelector('modus-wc-menu-item li');
li === null || li === void 0 ? void 0 : li.focus();
}
}
}