diff --git a/src/AsyncUserSelect/index.css b/src/AsyncUserSelect/index.css index 355e2b21..60f14e93 100644 --- a/src/AsyncUserSelect/index.css +++ b/src/AsyncUserSelect/index.css @@ -29,10 +29,15 @@ height: 12px; } -.dtable-ui-user-select-popover .popover { - width: 385px; +.dtable-ui-user-select-popover { + z-index: 1060; + width: 385px !important; max-width: 385px; margin-top: -4px; + background-color: var(--bs-popover-bg); + box-shadow: var(--bs-border-secondary-shadow); + border: 1px solid var(--bs-border-secondary-color); + border-radius: 4px; } .dtable-ui-user-select-container { @@ -58,6 +63,10 @@ border-radius: 4px; } +.dtable-ui-user-select-container .dtable-ui-user-list-container .dtable-ui-user-item-container .dtable-ui-user-item { + background: none !important; +} + .dtable-ui-user-select-container .dtable-ui-user-list-container .dtable-ui-user-item-container:hover, .dtable-ui-user-select-container .dtable-ui-user-list-container .dtable-ui-user-item-container-highlight { background-color: var(--bs-btn-background-hover); diff --git a/src/AsyncUserSelect/index.js b/src/AsyncUserSelect/index.js index 420aa46d..ecd92bce 100644 --- a/src/AsyncUserSelect/index.js +++ b/src/AsyncUserSelect/index.js @@ -1,8 +1,7 @@ -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import { Popover } from 'reactstrap'; -import ClickOutside from '../ClickOutside'; +import ModalPortal from '../ModalPortal'; import DTableCustomizeSearchInput from '../DTableCustomizeSearchInput'; import UserItem from './user-item'; import { getLocale } from '../lang'; @@ -18,6 +17,7 @@ const AsyncUserSelect = ({ className, emptyPlaceholder = '', searchPlaceholder = const [highlightIndex, setHighlightIndex] = useState(-1); const [maxItemNum, setMaxItemNum] = useState(0); const [itemHeight, setItemHeight] = useState(0); + const [popoverPosition, setPopoverPosition] = useState(null); const selectorRef = useRef(null); const userSelectContainerRef = useRef(null); @@ -30,13 +30,6 @@ const AsyncUserSelect = ({ className, emptyPlaceholder = '', searchPlaceholder = setHighlightIndex(-1); }, []); - const onClickOutside = useCallback((e) => { - if (isPopoverOpen && (!selectorRef.current || !selectorRef.current.contains(e.target))) { - setIsPopoverOpen(false); - clearStatus(); - } - }, [isPopoverOpen, clearStatus]); - const searchUsers = useCallback((searchValue = '') => { const trimmedSearchValue = searchValue?.trim() || ''; if (!trimmedSearchValue) { @@ -165,21 +158,14 @@ const AsyncUserSelect = ({ className, emptyPlaceholder = '', searchPlaceholder = }, [onEnter, onUpArrow, onDownArrow, onEsc]); useEffect(() => { - if (userSelectContainerRef.current) { - const { bottom } = userSelectContainerRef.current.getBoundingClientRect(); - if (bottom > window.innerHeight) { - userSelectContainerRef.current.style.top = `${window.innerHeight - bottom}px`; - } - } + if (!isPopoverOpen) return; if (userListContainerRef.current && userItemContainerRef.current) { - const userContainerStyle = getComputedStyle(userListContainerRef.current, null); - const userItemStyle = getComputedStyle(userItemContainerRef.current, null); - const userItemHeight = parseInt(userItemStyle.height); - const maxContainerItemNum = Math.floor(parseInt(userContainerStyle.maxHeight) / userItemHeight); - setMaxItemNum(maxContainerItemNum); + const userItemHeight = userItemContainerRef.current.getBoundingClientRect().height; + const listMaxHeight = userListContainerRef.current.clientHeight; setItemHeight(userItemHeight); + setMaxItemNum(Math.max(1, Math.floor(listMaxHeight / userItemHeight))); } - }, []); + }, [isPopoverOpen, searchedUsers]); useEffect(() => { document.addEventListener('keydown', onHotKey, true); @@ -188,80 +174,117 @@ const AsyncUserSelect = ({ className, emptyPlaceholder = '', searchPlaceholder = }; }, [onHotKey]); + useEffect(() => { + if (!isPopoverOpen) return; + const isInside = (target) => { + if (!target) return false; + if (selectorRef.current && selectorRef.current.contains(target)) return true; + if (userSelectContainerRef.current && userSelectContainerRef.current.contains(target)) return true; + return false; + }; + const handleDocumentMouseDown = (e) => { + if (isInside(e.target)) return; + setIsPopoverOpen(false); + clearStatus(); + }; + document.addEventListener('mousedown', handleDocumentMouseDown, true); + return () => { + document.removeEventListener('mousedown', handleDocumentMouseDown, true); + }; + }, [isPopoverOpen, clearStatus]); + + const getSelectorRect = () => { + if (!selectorRef.current) return null; + return selectorRef.current.getBoundingClientRect(); + }; + + useLayoutEffect(() => { + if (!isPopoverOpen) { + setPopoverPosition(null); + return; + } + const rect = getSelectorRect(); + if (!rect) return; + setPopoverPosition({ + position: 'fixed', + top: rect.bottom + 8, + left: rect.left, + width: rect.width, + }); + }, [isPopoverOpen, selectedUsers]); + + const popoverStyle = popoverPosition; + return ( - - <> -
-
- {selectedUsers.map((user, index) => { - return ( - - ); - })} - {selectedUsers.length === 0 && ( -
- {emptyPlaceholder || getLocale('Search_users')} -
- )} - {!showDeptBtn && } -
+ <> +
+
+ {selectedUsers.map((user, index) => { + return ( + + ); + })} + {selectedUsers.length === 0 && ( +
+ {emptyPlaceholder || getLocale('Search_users')} +
+ )} + {!showDeptBtn && }
- {selectorRef.current && ( - + {isPopoverOpen && popoverStyle && ( + +
e.stopPropagation()} > -
e.stopPropagation()}> -
- onSearchValueChanged('')} - autoFocus={true} - isClearable={true} - value={searchValue} - /> -
-
- {searchedUsers.length > 0 && ( - searchedUsers.map((user, index) => { - return ( -
onUserClick(user)} - > - - {selectedUsers.find(u => u.email === user.email) && ( -
- -
- )} -
- ); - }) - )} - {searchedUsers.length === 0 && -
- {searchValue ? getLocale('User_not_found') : getLocale('Enter_characters_to_start_searching')} -
- } -
+
+ onSearchValueChanged('')} + autoFocus={true} + isClearable={true} + value={searchValue} + /> +
+
+ {searchedUsers.length > 0 && ( + searchedUsers.map((user, index) => { + return ( +
onUserClick(user)} + > + + {selectedUsers.find(u => u.email === user.email) && ( +
+ +
+ )} +
+ ); + }) + )} + {searchedUsers.length === 0 && ( +
+ {searchValue ? getLocale('User_not_found') : getLocale('Enter_characters_to_start_searching')} +
+ )}
- - )} - - +
+ + )} + ); }; diff --git a/src/DTableCustomizeSearchInput/index.css b/src/DTableCustomizeSearchInput/index.css index ef080b65..c1f094fd 100644 --- a/src/DTableCustomizeSearchInput/index.css +++ b/src/DTableCustomizeSearchInput/index.css @@ -28,6 +28,18 @@ border-top-right-radius: 4px; } +.select-search-control:-webkit-autofill, +.select-search-control:-webkit-autofill:hover, +.select-search-control:-webkit-autofill:focus, +.select-search-control:-webkit-autofill:active, +.select-search-control:-internal-autofill-previewed, +.select-search-control:-internal-autofill-selected { + -webkit-box-shadow: inset 0 0 0 1000px var(--bs-popover-bg) !important; + box-shadow: inset 0 0 0 1000px var(--bs-popover-bg) !important; + -webkit-text-fill-color: var(--bs-body-color) !important; + transition: background-color 5000s ease-in-out 0s !important; +} + .select-search-control:focus { outline: none; box-shadow: none; @@ -70,6 +82,6 @@ .dtable-ui-user-select-popover .select-search-control, .dtable-popover .select-search-control { - border-top-left-radius: 8px; - border-top-right-radius: 8px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; } diff --git a/src/DTableCustomizeSelect/index.css b/src/DTableCustomizeSelect/index.css index 8ab81935..9a5f50ed 100644 --- a/src/DTableCustomizeSelect/index.css +++ b/src/DTableCustomizeSelect/index.css @@ -107,10 +107,6 @@ white-space: nowrap; } -.seatable-customize-select .selected-option .multicolor-icon { - font-size: 12px; -} - .seatable-customize-select .multiple-check-icon, .seatable-customize-select .header-icon .dtable-font, .seatable-option-group .select-label .header-icon .dtable-font { @@ -125,6 +121,12 @@ margin-left: 0 !important; } +.seatable-customize-select .selected-option .dtable-icon-down3, +.seatable-customize-select .selected-option .multicolor-icon { + color: var(--bs-icon-color) !important; + font-size: 12px; +} + .selector-group-select .selected-option-show .selected-option-item { align-items: center; border-radius: 4px; @@ -159,7 +161,9 @@ } .selector-group-select { - padding: 7px 16px 7px 8px; + height: auto; + min-height: 38px; + padding: 6px 16px 6px 8px; } .selector-group-select .selected-option { @@ -172,7 +176,3 @@ height: auto; min-height: 24px } - -.selector-group-select { - height: auto; -} diff --git a/src/DTableCustomizeSelect/index.js b/src/DTableCustomizeSelect/index.js index d4c725f4..6225d1cb 100644 --- a/src/DTableCustomizeSelect/index.js +++ b/src/DTableCustomizeSelect/index.js @@ -46,6 +46,22 @@ class DTableCustomizeSelect extends Component { this.setState({ isShowSelectOptions: false }); }; + handleDocumentMouseDown = (event) => { + if (!this.state.isShowSelectOptions) return; + const target = event.target; + if (this.selector && this.selector.contains(target)) return; + if (target && target.closest && target.closest('.seatable-option-group')) return; + this.closeSelect(); + }; + + componentDidMount() { + document.addEventListener('mousedown', this.handleDocumentMouseDown, true); + } + + componentWillUnmount() { + document.removeEventListener('mousedown', this.handleDocumentMouseDown, true); + } + getSelectedOptionTop = () => { if (!this.selector) return 38; const { height } = this.selector.getBoundingClientRect(); diff --git a/src/DTableFiltersPopover/widgets/filter-list/index.css b/src/DTableFiltersPopover/widgets/filter-list/index.css index 44695aec..508eeb04 100644 --- a/src/DTableFiltersPopover/widgets/filter-list/index.css +++ b/src/DTableFiltersPopover/widgets/filter-list/index.css @@ -132,7 +132,7 @@ } .dtable-ui-filters-list .filter-conjunction { - width: 72px; + width: 88px; } .dtable-ui-filters-list .filter-conjunction-readonly { @@ -166,21 +166,12 @@ color: #666666; } -.dtable-ui-filters-list .filter-column { - max-width: 150px; -} - .filter-term .dtable-ui-multiple-select-selector .option, .filter-term .dtable-ui-single-select-selector .option { height: 30px; padding: 0 10px; } -.filter-term .dtable-ui-multiple-select-selector .select-option-name, -.filter-term .dtable-ui-single-select-selector .select-option-name { - margin-top: 5px !important; -} - .filter-term .dtable-ui-single-select-selector .option:hover { color: #212529; background-color: #f7f7f7; diff --git a/src/DTableSelect/dtable-select-label.css b/src/DTableSelect/dtable-select-label.css index acc87b1d..7868d6a0 100644 --- a/src/DTableSelect/dtable-select-label.css +++ b/src/DTableSelect/dtable-select-label.css @@ -9,7 +9,15 @@ color: var(--bs-icon-color); } -.seatable-option .select-option-name .seatable-tip-default { +.seatable-option .seatable-tip-default { font-size: 12px; margin-top: 4px } + +.select-option-name .group-select-option, +.seatable-option.option-name { + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/src/DTableSelect/utils.js b/src/DTableSelect/utils.js index da0c6f4e..8e3b9fc3 100644 --- a/src/DTableSelect/utils.js +++ b/src/DTableSelect/utils.js @@ -215,7 +215,7 @@ const Option = props => { return (
-
{label}
+
{label}
{isSelected && }
diff --git a/src/SelectOptionGroup/index.css b/src/SelectOptionGroup/index.css index 0320ace4..c67b5ccf 100644 --- a/src/SelectOptionGroup/index.css +++ b/src/SelectOptionGroup/index.css @@ -66,6 +66,9 @@ .select-label { width: 100%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } .seatable-option-group-selector-multiple-select .select-label,