@douyinfe/semi-ui
Version:
A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.
199 lines • 7.37 kB
JavaScript
import _pick from "lodash/pick";
import _noop from "lodash/noop";
import _isEqual from "lodash/isEqual";
import React, { isValidElement, useEffect, useState } from 'react';
import cls from 'classnames';
import { IconFilter } from '@douyinfe/semi-icons';
import { cssClasses } from '@douyinfe/semi-foundation/lib/es/table/constants';
import Dropdown from '../dropdown';
import { Radio } from '../radio';
import { Checkbox } from '../checkbox';
function renderDropdown(props) {
let nestedElem = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
let level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
const {
filterMultiple = true,
filters = [],
filteredValue = [],
filterDropdownVisible,
onSelect = _noop,
onFilterDropdownVisibleChange = _noop,
trigger = 'click',
position = 'bottom',
renderFilterDropdown,
renderFilterDropdownItem
} = props !== null && props !== void 0 ? props : {};
const renderFilterDropdownProps = _pick(props, ['tempFilteredValue', 'setTempFilteredValue', 'confirm', 'clear', 'close', 'filters']);
const render = typeof renderFilterDropdown === 'function' ? renderFilterDropdown(renderFilterDropdownProps) : (/*#__PURE__*/React.createElement(Dropdown.Menu, null, Array.isArray(filters) && filters.map((filter, index) => {
const changeFn = e => {
const domEvent = e && e.nativeEvent;
if (domEvent) {
// Block this event to prevent the pop-up layer from closing
domEvent.stopImmediatePropagation();
// Prevent bubbling and default events to prevent label click events from triggering twice
domEvent.stopPropagation();
domEvent.preventDefault();
}
let values = [...filteredValue];
const included = values.includes(filter.value);
const idx = values.indexOf(filter.value);
if (idx > -1) {
values.splice(idx, 1);
} else if (filterMultiple) {
values.push(filter.value);
} else {
values = [filter.value];
}
return onSelect({
value: filter.value,
filteredValue: values,
included: !included,
domEvent
});
};
const checked = filteredValue.includes(filter.value);
const {
text
} = filter;
const {
value
} = filter;
const key = `${level}_${index}`;
const dropdownItem = typeof renderFilterDropdownItem === 'function' ? renderFilterDropdownItem({
onChange: changeFn,
filterMultiple,
value,
text,
checked,
filteredValue,
level
}) : null;
let item = dropdownItem && /*#__PURE__*/React.isValidElement(dropdownItem) ? (/*#__PURE__*/React.cloneElement(dropdownItem, {
key
})) : (/*#__PURE__*/React.createElement(Dropdown.Item, {
key: key,
onClick: changeFn
}, filterMultiple ? (/*#__PURE__*/React.createElement(Checkbox, {
checked: checked
}, text)) : (/*#__PURE__*/React.createElement(Radio, {
checked: checked
}, text))));
if (Array.isArray(filter.children) && filter.children.length) {
const childrenDropdownProps = Object.assign(Object.assign({}, props), {
filters: filter.children,
trigger: 'hover',
position: 'right'
});
delete childrenDropdownProps.filterDropdownVisible;
item = renderDropdown(childrenDropdownProps, item, level + 1);
}
return item;
})));
const dropdownProps = Object.assign(Object.assign({}, props), {
onVisibleChange: visible => onFilterDropdownVisibleChange(visible),
trigger,
position,
render
});
if (filterDropdownVisible != null) {
dropdownProps.visible = filterDropdownVisible;
}
return /*#__PURE__*/React.createElement(Dropdown, Object.assign({}, dropdownProps, {
key: `Dropdown_level_${level}`,
className: `${cssClasses.PREFIX}-column-filter-dropdown`
}), nestedElem);
}
export default function ColumnFilter() {
let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
const {
prefixCls = cssClasses.PREFIX,
filteredValue,
filterIcon = 'filter',
filterDropdownProps,
onSelect,
filterDropdownVisible,
renderFilterDropdown,
onFilterDropdownVisibleChange
} = props;
let {
filterDropdown = null
} = props;
// custom filter related status
const isFilterDropdownVisibleControlled = typeof filterDropdownVisible !== 'undefined';
const isCustomFilterDropdown = typeof renderFilterDropdown === 'function';
const isCustomDropdownVisible = !isFilterDropdownVisibleControlled && isCustomFilterDropdown;
const [tempFilteredValue, setTempFilteredValue] = useState(filteredValue);
const dropdownVisibleInitValue = isCustomDropdownVisible ? false : filterDropdownVisible;
const [dropdownVisible, setDropdownVisible] = useState(dropdownVisibleInitValue);
useEffect(() => {
if (typeof filterDropdownVisible !== 'undefined') {
setDropdownVisible(filterDropdownVisible);
}
}, [filterDropdownVisible]);
useEffect(() => {
setTempFilteredValue(filteredValue);
}, [filteredValue]);
const confirm = function () {
let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
const newFilteredValue = (props === null || props === void 0 ? void 0 : props.filteredValue) || tempFilteredValue;
if (!_isEqual(newFilteredValue, filteredValue)) {
onSelect({
filteredValue: newFilteredValue
});
}
if (props.closeDropdown) {
setDropdownVisible(false);
}
};
const clear = function () {
let props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
setTempFilteredValue([]);
onSelect({
filteredValue: []
});
if (props.closeDropdown) {
setDropdownVisible(false);
}
};
const close = () => {
setDropdownVisible(false);
};
const handleFilterDropdownVisibleChange = visible => {
if (isCustomDropdownVisible) {
setDropdownVisible(visible);
}
onFilterDropdownVisibleChange(visible);
};
const renderFilterDropdownProps = {
tempFilteredValue,
setTempFilteredValue,
confirm,
clear,
close
};
const finalCls = cls(`${prefixCls}-column-filter`, {
on: Array.isArray(filteredValue) && filteredValue.length
});
let iconElem;
if (typeof filterIcon === 'function') {
iconElem = filterIcon(Array.isArray(filteredValue) && filteredValue.length > 0);
} else if (/*#__PURE__*/isValidElement(filterIcon)) {
iconElem = filterIcon;
} else {
iconElem = /*#__PURE__*/React.createElement("div", {
className: finalCls
}, '\u200b' /* ZWSP(zero-width space) */, /*#__PURE__*/React.createElement(IconFilter, {
role: "button",
"aria-label": "Filter data with this column",
"aria-haspopup": "listbox",
tabIndex: -1,
size: "default"
}));
}
const renderProps = Object.assign(Object.assign(Object.assign(Object.assign({}, props), filterDropdownProps), renderFilterDropdownProps), {
filterDropdownVisible: isFilterDropdownVisibleControlled ? filterDropdownVisible : dropdownVisible,
onFilterDropdownVisibleChange: handleFilterDropdownVisibleChange
});
filterDropdown = /*#__PURE__*/React.isValidElement(filterDropdown) ? filterDropdown : renderDropdown(renderProps, iconElem);
return filterDropdown;
}