UNPKG

@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
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; }