UNPKG

@trail-ui/react

Version:
157 lines (154 loc) 7.38 kB
import { _Chip } from "./chunk-PGQ46KYE.mjs"; import { _Button } from "./chunk-VGPOEUEE.mjs"; // src/tanstackTable/tanstack-table-faceted-filter.tsx import * as React from "react"; import { CheckIcon, ChevronDownIcon, ChevronUpIcon, CloseIcon } from "@trail-ui/icons"; import { commonColors } from "@trail-ui/theme"; import { jsx, jsxs } from "react/jsx-runtime"; function TanstackTableFacetedFilter({ column, title, options, selectedFilterValues, setSelectedFilterValues // openFilter, }) { var _a; const facets = column == null ? void 0 : column.getFacetedUniqueValues(); const selectedValues = new Set(column == null ? void 0 : column.getFilterValue()); const [openFilterOptions, setOpenFilterOptions] = React.useState(false); const filterOptionsToShow = 5; const [loadMore, setLoadMore] = React.useState(filterOptionsToShow); const optionsRef = React.useRef([]); const [focusedIndex, setFocusedIndex] = React.useState(null); function handleLoadMore() { const prevLoadMore = loadMore; setLoadMore((prev) => prev + filterOptionsToShow); setTimeout(() => { var _a2; if (optionsRef.current[prevLoadMore]) { (_a2 = optionsRef.current[prevLoadMore]) == null ? void 0 : _a2.focus(); } }, 0); } React.useEffect(() => { var _a2; if (focusedIndex !== null && optionsRef.current[focusedIndex]) { (_a2 = optionsRef.current[focusedIndex]) == null ? void 0 : _a2.focus(); } }, [focusedIndex, loadMore]); function handleKeyDown(event, index) { var _a2; if (event.key === "ArrowDown") { setFocusedIndex((prev) => prev !== null && prev < loadMore - 1 ? prev + 1 : 0); } else if (event.key === "ArrowUp") { setFocusedIndex((prev) => prev !== null && prev > 0 ? prev - 1 : loadMore - 1); } else if (event.key === "Enter" || event.key === " ") { event.preventDefault(); (_a2 = optionsRef.current[index]) == null ? void 0 : _a2.click(); } } return /* @__PURE__ */ jsx("div", { className: "relative flex flex-col items-center after:absolute after:bottom-0 after:left-3 after:block after:h-[1px] after:w-full after:bg-neutral-200 last:after:bg-neutral-50", children: /* @__PURE__ */ jsxs("div", { className: "w-full bg-neutral-50 p-0", children: [ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-4 py-[10px]", children: /* @__PURE__ */ jsxs( _Button, { "aria-expanded": openFilterOptions ? true : false, id: `filter-${title}`, "aria-controls": `sect-${title}`, onPress: () => setOpenFilterOptions(!openFilterOptions), className: "flex flex-1 justify-between px-0", appearance: "transparent", children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-neutral-700", children: title }), /* @__PURE__ */ jsxs("p", { className: "text-sm font-normal text-neutral-700", children: [ "(", selectedValues.size, " selected)" ] }) ] }), openFilterOptions ? /* @__PURE__ */ jsx(ChevronUpIcon, { width: 24, height: 24, color: commonColors.neutral[800] }) : /* @__PURE__ */ jsx(ChevronDownIcon, { width: 24, height: 24, color: commonColors.neutral[800] }) ] } ) }), /* @__PURE__ */ jsxs( "ul", { id: `sect-${title}`, "aria-labelledby": `filter-${title}`, className: `${openFilterOptions ? "h-auto max-h-60 overflow-auto" : "h-0 max-h-0 overflow-hidden"} flex flex-col transition-all`, children: [ (_a = options == null ? void 0 : options.slice(0, loadMore)) == null ? void 0 : _a.map((option, index) => { const isSelected = selectedFilterValues.has(option.value); const statusStyles = { completed: { bgColor: "bg-green-50", borderColor: "border border-green-950" }, regression: { bgColor: "bg-red-50", borderColor: "border-red-950" }, inProgress: { bgColor: "bg-yellow-50", borderColor: "border-yellow-950" } }; const { completed } = statusStyles; return /* @__PURE__ */ jsx("li", { className: "h-full last:mb-2", children: /* @__PURE__ */ jsxs( "button", { ref: (el) => optionsRef.current[index] = el, tabIndex: openFilterOptions ? 0 : -1, onKeyDown: (event) => handleKeyDown(event, index), className: ` ${isSelected && "border-l-[3px] !border-l-purple-600 bg-purple-50 font-semibold"} flex h-10 w-full items-center justify-between rounded-none border-l-[3px] border-l-transparent px-4 text-left text-sm text-neutral-900 transition-all hover:border-l-purple-600 hover:bg-purple-50 focus:border-purple-600`, onClick: () => { const updatedSelectedValues = new Set(selectedFilterValues); if (isSelected) { updatedSelectedValues.delete(option.value); } else { updatedSelectedValues.add(option.value); } setSelectedFilterValues(updatedSelectedValues); }, children: [ option.icon && /* @__PURE__ */ jsx(option.icon, { className: "text-muted-foreground mr-2 h-4 w-4" }), (column == null ? void 0 : column.id) === "status" ? /* @__PURE__ */ jsx( _Chip, { tabIndex: 0, classNames: { base: `${option.value === "Completed" ? completed.bgColor + " " + completed.borderColor : option.value === "In Progress" ? "border border-yellow-950 bg-yellow-50" : option.value === "Regression" ? "border border-red-950 bg-red-50" : ""} ${!isSelected && "!border-0"} pointer-events-none` }, color: "default", endContent: isSelected ? /* @__PURE__ */ jsx(CloseIcon, { width: 16, height: 16 }) : "", children: option.label } ) : /* @__PURE__ */ jsx("span", { className: "w-full text-left", children: option.label }), (facets == null ? void 0 : facets.get(option.value)) && /* @__PURE__ */ jsx("span", { className: "ml-auto flex h-4 w-4 items-center justify-center font-mono text-xs", children: facets.get(option.value) }), isSelected ? /* @__PURE__ */ jsx(CheckIcon, { width: 24, height: 24, color: commonColors.purple[600] }) : "" ] } ) }, option.label); }), /* @__PURE__ */ jsx("li", { className: "flex justify-center pb-2", children: loadMore < options.length && /* @__PURE__ */ jsx( "button", { tabIndex: openFilterOptions ? 0 : -1, className: "text-sm font-medium text-purple-600", onClick: handleLoadMore, children: "View More" } ) }) ] } ) ] }) }); } export { TanstackTableFacetedFilter };