@trail-ui/react
Version:
157 lines (154 loc) • 7.38 kB
JavaScript
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
};