@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
166 lines (165 loc) • 6.83 kB
JavaScript
"use client";
import { ScrollArea } from "../ScrollArea/ScrollArea.mjs";
import { UnstyledButton } from "../UnstyledButton/UnstyledButton.mjs";
import { AccordionChevron } from "../Accordion/AccordionChevron.mjs";
import { CheckIcon } from "../Checkbox/CheckIcon.mjs";
import { cascaderOptionHasChildren, getCascaderColumns } from "./get-cascader-columns.mjs";
import { useCascaderSafeArea } from "./use-cascader-safe-area.mjs";
import { useRef, useState } from "react";
import { jsx, jsxs } from "react/jsx-runtime";
//#region packages/@mantine/core/src/components/Cascader/CascaderColumns.tsx
function getCascaderOptionId(listId, level, value) {
return listId ? `${listId}-${level}-${value}` : void 0;
}
function CascaderColumns({ data, activePath, value, keyboardNav, withCheckIcon, checkIconPosition, renderOption, columnWidth, maxDisplayedLevels, previousLevelsControlLabel, nextLevelsControlLabel, maxDropdownHeight, nothingFoundMessage, getStyles, unstyled, scrollAreaProps, onOptionClick, onOptionMouseEnter, onColumnsMouseLeave, onPointerActivity, listId, safeAreaPolygon }) {
const allColumns = getCascaderColumns(data, activePath);
const totalColumns = allColumns.length;
const maxLevels = maxDisplayedLevels && maxDisplayedLevels > 0 ? maxDisplayedLevels : totalColumns;
const maxOffset = Math.max(0, totalColumns - maxLevels);
const focusedLevel = activePath.length - 1;
const showCheckIcon = withCheckIcon !== false;
const activePathKey = JSON.stringify(activePath);
const [windowState, setWindowState] = useState({
key: activePathKey,
offset: 0
});
const windowOffset = windowState.key === activePathKey ? windowState.offset : 0;
if (windowState.key !== activePathKey) setWindowState({
key: activePathKey,
offset: 0
});
const setWindowOffset = (updater) => setWindowState((current) => ({
key: activePathKey,
offset: updater(current.offset)
}));
const windowStart = Math.max(0, maxOffset - Math.min(windowOffset, maxOffset));
const windowEnd = Math.min(totalColumns, windowStart + maxLevels);
const visibleColumns = allColumns.slice(windowStart, windowEnd);
const hiddenBefore = windowStart;
const hiddenAfter = totalColumns - windowEnd;
const check = showCheckIcon ? /* @__PURE__ */ jsx(CheckIcon, { ...getStyles("columnOptionCheck") }) : null;
const columnRefs = useRef({});
const safeArea = useCascaderSafeArea({
safeAreaPolygon,
onFlush: onOptionMouseEnter
});
return /* @__PURE__ */ jsxs("div", {
...getStyles("columnsList"),
role: "presentation",
onMouseLeave: () => {
safeArea.disarm();
onColumnsMouseLeave?.();
},
onMouseMove: onPointerActivity,
children: [
hiddenBefore > 0 && /* @__PURE__ */ jsx(UnstyledButton, {
...getStyles("columnsOverflow"),
"data-position": "start",
tabIndex: -1,
unstyled,
"aria-label": previousLevelsControlLabel,
title: previousLevelsControlLabel,
onMouseDown: (event) => event.preventDefault(),
onClick: () => setWindowOffset((current) => Math.min(maxOffset, current + 1)),
children: /* @__PURE__ */ jsx(AccordionChevron, {})
}),
visibleColumns.map((options, index) => {
const level = windowStart + index;
return /* @__PURE__ */ jsx("div", {
ref: (node) => {
columnRefs.current[level] = node;
},
"data-last": index === visibleColumns.length - 1 && hiddenAfter === 0 || void 0,
...getStyles("column", { style: columnWidth ? {
width: columnWidth,
minWidth: columnWidth
} : void 0 }),
children: /* @__PURE__ */ jsx(ScrollArea.Autosize, {
mah: maxDropdownHeight ?? 260,
type: "scroll",
scrollbarSize: "var(--combobox-padding)",
role: "listbox",
...scrollAreaProps,
...getStyles("columnScroll"),
children: options.length === 0 ? /* @__PURE__ */ jsx("div", {
...getStyles("columnEmpty"),
children: nothingFoundMessage
}) : options.map((option) => {
const isActive = activePath[level] === option.value;
const isCurrent = isActive && level === focusedLevel && keyboardNav;
const isInPath = isActive && level < focusedLevel;
const hasChildren = cascaderOptionHasChildren(option);
const isSelected = !!value && value.length === level + 1 && value[level] === option.value;
return /* @__PURE__ */ jsxs(UnstyledButton, {
id: getCascaderOptionId(listId, level, option.value),
role: "option",
"aria-selected": isCurrent || void 0,
"aria-disabled": option.disabled || void 0,
"data-active": isCurrent || void 0,
"data-in-path": isInPath || void 0,
"data-selected": isSelected || void 0,
"data-disabled": option.disabled || void 0,
tabIndex: -1,
unstyled,
onMouseDown: (event) => event.preventDefault(),
onClick: () => {
if (!option.disabled) onOptionClick(level, option);
},
onMouseEnter: () => {
if (option.disabled) return;
if (safeArea.isBlocked(level)) {
safeArea.setPending(level, option);
return;
}
onOptionMouseEnter(level, option);
},
onMouseLeave: (event) => {
safeArea.clearPending(level, option);
if (!safeArea.enabled || option.disabled) return;
if (activePath[level] !== option.value) return;
const floating = columnRefs.current[level + 1];
if (!floating) return;
safeArea.arm({
level,
reference: event.currentTarget,
floating,
clientX: event.clientX,
clientY: event.clientY
});
},
...getStyles("columnOption"),
children: [
isSelected && checkIconPosition === "left" && check,
/* @__PURE__ */ jsx("span", {
...getStyles("columnOptionLabel"),
children: renderOption ? renderOption(option, level) : option.label ?? option.value
}),
isSelected && checkIconPosition !== "left" && check,
hasChildren && /* @__PURE__ */ jsx("span", {
...getStyles("columnOptionIcon"),
children: /* @__PURE__ */ jsx(AccordionChevron, {})
})
]
}, option.value);
})
})
}, level);
}),
hiddenAfter > 0 && /* @__PURE__ */ jsx(UnstyledButton, {
...getStyles("columnsOverflow"),
"data-position": "end",
tabIndex: -1,
unstyled,
"aria-label": nextLevelsControlLabel,
title: nextLevelsControlLabel,
onMouseDown: (event) => event.preventDefault(),
onClick: () => setWindowOffset((current) => Math.max(0, current - 1)),
children: /* @__PURE__ */ jsx(AccordionChevron, {})
})
]
});
}
CascaderColumns.displayName = "@mantine/core/CascaderColumns";
//#endregion
export { CascaderColumns, getCascaderOptionId };
//# sourceMappingURL=CascaderColumns.mjs.map