@adaptabletools/adaptable
Version:
Powerful AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
105 lines (104 loc) • 7.37 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import * as React from 'react';
import SimpleButton from '../../../components/SimpleButton';
import { useAdaptable } from '../../AdaptableContext';
import { AdaptableIconComponent } from '../AdaptableIconComponent';
import { SingleSelect } from '../../../components/NewSelect';
import { FloatingFilterInputList } from './components/FloatingFilterInputList';
import { isPredicateEmpty, qlPredicateToString } from './utils';
import { AG_GRID_GROUPED_COLUMN } from '../../../Utilities/Constants/GeneralConstants';
import { Box, Flex } from '../../../components/Flex';
import { cn, getFocusableElements } from '../../../lib/utils';
import { Maximize2 } from 'lucide-react';
export const FloatingFilter = (props) => {
const adaptable = useAdaptable();
const isMultiple = props.predicate?.args?.length > 1;
const isManualApply = adaptable.api.filterApi.columnFilterApi.internalApi.shouldManuallyApplyColumnFilter(props.columnId);
const isInlineEditable = !isMultiple && !isManualApply;
let singleFilterPredicateDef = null;
if (props.predicate.args.length === 1) {
singleFilterPredicateDef = props.predicateDefs.find((predicateDef) => predicateDef.operator === props.predicate.args[0].operator);
}
const noInputs = !singleFilterPredicateDef?.inputs || singleFilterPredicateDef.inputs.length === 0;
let showLabel = isMultiple || noInputs || isManualApply;
if (props.columnId === AG_GRID_GROUPED_COLUMN) {
showLabel = false;
}
let label = qlPredicateToString(props.predicate, props.predicateDefs);
if (isManualApply &&
singleFilterPredicateDef &&
isPredicateEmpty(props.predicate.args[0], singleFilterPredicateDef)) {
label = '';
}
const showQuickFilterDropdown = adaptable.api.filterApi.columnFilterApi.internalApi.showQuickFilterDropdown(props.columnId);
const colDef = adaptable.api.columnApi.getAGGridColDefForColumnId(props.columnId);
const showExpandFilterButton = colDef?.suppressHeaderFilterButton !== true;
const handleClear = () => props.onClear?.();
const [selectOpen, setSelectOpen] = React.useState(false);
const currentOperator = props.predicate?.args[0]?.operator;
const operatorOptions = props.predicateDefs.map((predicateDef) => ({
label: (_jsxs(Box, { className: "twa:flex twa:items-center", children: [_jsx(Box, { className: "twa:mr-2 twa:flex twa:items-center", children: predicateDef.icon }), _jsx(Box, { className: "twa:truncate", "data-name": "filter-predicate-label", "data-label": predicateDef.label, children: predicateDef.label })] })),
tooltip: predicateDef.label,
ariaLabel: predicateDef.label,
value: predicateDef.operator,
}));
const renderTriggerValue = () => (_jsxs(Flex, { alignItems: "center", className: "twa:min-w-0", children: [_jsx(Box, { className: "twa:flex twa:items-center", children: !isManualApply && singleFilterPredicateDef?.icon ? (singleFilterPredicateDef?.icon) : (_jsx(AdaptableIconComponent, { icon: { name: 'filter' } })) }), showLabel && (_jsx(Box, { className: "ab-FloatingFilter-label twa:ml-2 twa:flex-1 twa:truncate", title: label, children: label }))] }));
let filterDropdown = null;
const filterDropdownSelect = (_jsx("div", { className: cn('twa:flex twa:box-border twa:self-stretch twa:min-h-0 twa:h-full twa:py-0.5 twa:px-0.5', !isInlineEditable && 'twa:min-w-0 twa:flex-1'), children: _jsx(SingleSelect, { chevronIcon: null, "data-name": "floating-filter-button", ariaLabel: `Column Filter Operator Dropdown: current operator is ${label}`, stopMouseDownPropagation: true, disabled: props.disabled, open: selectOpen, extraWidthChars: 5, onOpenChange: (nextOpen) => {
if (nextOpen && !isInlineEditable) {
adaptable.api.filterApi.columnFilterApi.internalApi.openColumnFilterPopup(props.columnId);
return;
}
setSelectOpen(nextOpen);
}, value: currentOperator, placeholder: label, items: operatorOptions, showItemTooltip: true, renderValue: renderTriggerValue, onValueChange: (operator) => {
props.onPredicateChange({
operator: props.predicate.operator,
args: [{ operator: operator, args: [] }],
});
}, className: cn('twa:h-full twa:w-full twa:min-h-0 twa:text-left twa:px-0.5 twa:py-0.5 twa:border-none', 'twa:shadow-none twa:cursor-pointer', 'twa:text-primary-foreground twa:hover:bg-current/15') }) }));
if (isInlineEditable) {
filterDropdown = showQuickFilterDropdown && filterDropdownSelect;
}
else {
filterDropdown = filterDropdownSelect;
}
const showClearButton = isMultiple ||
!isPredicateEmpty(props.predicate.args[0], singleFilterPredicateDef);
return (_jsxs(Flex, { className: "ab-FloatingFilter twa:w-full", onKeyDownCapture: (e) => {
if (e.key !== 'Tab') {
return;
}
const wrapper = e.currentTarget;
const focusable = getFocusableElements(wrapper);
if (focusable.length === 0) {
return;
}
const active = document.activeElement;
const currentIndex = active ? focusable.indexOf(active) : -1;
if (currentIndex === -1) {
return;
}
const nextIndex = currentIndex + (e.shiftKey ? -1 : 1);
if (nextIndex < 0 || nextIndex >= focusable.length) {
return;
}
e.preventDefault();
e.nativeEvent.stopImmediatePropagation();
focusable[nextIndex]?.focus();
requestAnimationFrame(() => {
if (document.activeElement === document.body || document.activeElement === null) {
const refreshed = getFocusableElements(wrapper);
refreshed[Math.min(nextIndex, refreshed.length - 1)]?.focus();
}
});
}, children: [filterDropdown, isInlineEditable && (_jsx(Flex, { className: "twa:flex-1 twa:min-w-0 twa:min-h-0 twa:h-full", children: _jsx(FloatingFilterInputList, { onKeyDown: props.onKeydown, columnId: props.columnId, disabled: props.disabled, predicate: props.predicate.args[0], predicateDefs: props.predicateDefs, onPredicateChange: (predicate) => {
props.onPredicateChange({
operator: props.predicate.operator,
args: [predicate],
});
} }) })), isInlineEditable && showExpandFilterButton && (_jsx(SimpleButton, { className: cn('twa:px-1 twa:my-0.5', !showClearButton && 'twa:mr-0.5'), "aria-label": "Expand filter", tooltip: "Open filter popup", onClick: () => {
adaptable.api.filterApi.columnFilterApi.internalApi.openColumnFilterPopup(props.columnId, {
onChange: props.onChange,
});
}, "data-name": "expand-filter", icon: _jsx(Maximize2, { size: 20, strokeWidth: 1.5 }), variant: "text" })), showClearButton && (_jsx(SimpleButton, { "data-name": "clear-filter", className: "twa:p-0 twa:my-0.5 twa:mr-0.5", variant: "text", onClick: handleClear, icon: "close", tooltip: "Clear filter" }))] }));
};