Skip to content

Commit

Permalink
feat: Select自动切换方向支持小程序、优化第一次切方向时滑入方向不对问题
Browse files Browse the repository at this point in the history
  • Loading branch information
zhubeniii committed Feb 5, 2025
1 parent b270f76 commit 55fedb1
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 54 deletions.
14 changes: 9 additions & 5 deletions packages/bui-core/src/Portal/Portal.miniapp.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import Taro from '@tarojs/taro';
import React, { forwardRef, useMemo } from 'react';
import React, { forwardRef, useEffect, useState } from 'react';
import { PortalProps } from './Portal.types';
import PortalCore from './PortalCore';

export const Portal = forwardRef<HTMLElement, PortalProps>((props, ref) => {
const { disablePortal } = props;
const rootWrapperElement = useMemo(() => {
const [rootWrapperElement, setRootWrapperElement] = useState<HTMLElement>();

useEffect(() => {
let root;
if (!disablePortal) {
const currentPages = Taro.getCurrentPages() || [];
const currentPage = currentPages[currentPages.length - 1];
Expand All @@ -21,11 +24,12 @@ export const Portal = forwardRef<HTMLElement, PortalProps>((props, ref) => {
const view = document.createElement('view');
view.id = portalId;
rootElement?.appendChild(view);
return view;
root = view;
} else {
root = portalWrapperElement;
}
return portalWrapperElement;
}
return undefined;
setRootWrapperElement(root);
}, []);

return <PortalCore {...props} ref={ref} rootElement={rootWrapperElement} />;
Expand Down
4 changes: 0 additions & 4 deletions packages/bui-core/src/Select/Select.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
@class-prefix-select: ~'bui-select';
@transition-duration: 0.3s;

.@{class-prefix-select} {
--height: var(--bui-select-height, 27px);
Expand Down Expand Up @@ -58,9 +57,6 @@
&-option-container {
position: absolute;
box-sizing: border-box;
top: 100%;
left: 0;
width: 100%;
font-size: var(--bui-select-font-size, var(--bui-title-size-3));
z-index: var(--bui-z-index-tooltip);
border-radius: 3px;
Expand Down
66 changes: 32 additions & 34 deletions packages/bui-core/src/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,33 +56,32 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
const locatorRef = useRef(null);
const rootRef = useForkRef(ref, locatorRef);
const optionContainerRef = useRef(null);
const optionMainRef = useRef(null);

const updateOptionStyle = throttle(async () => {
const updateOptionStyle = async () => {
const curScrollRoot = scrollContainer();
if (!isMini && curScrollRoot) {
const result = await getStylesAndLocation({
scrollRoot: curScrollRoot,
childrenRef: locatorRef,
tipRef: optionContainerRef,
arrowDirection: defaultPlacement,
arrowLocation: 'none',
offsetSpacing: 0,
});
if (!result) return;
const { styles, childrenStyle, newArrowDirection } = result;
setPlacement(newArrowDirection);
setOptionStyle({ ...styles, width: childrenStyle?.width });
}
}, 100);
const result = await getStylesAndLocation({
scrollRoot: curScrollRoot,
childrenRef: locatorRef,
tipRef: optionContainerRef,
arrowDirection: defaultPlacement,
arrowLocation: 'none',
offsetSpacing: 0,
});
if (!result) return;
const { styles, childrenStyle, newArrowDirection } = result;
optionMainRef.current.style.transition = 'none';
optionMainRef.current.style.transform = `translateY(${newArrowDirection === 'bottom' ? '-100%' : '100%'})`;
setPlacement(newArrowDirection);
setOptionStyle({ ...styles, width: childrenStyle?.width });
};

const changeOpen = (newOpen: boolean) => {
const changeOpen = async (newOpen: boolean) => {
if (newOpen) {
updateOptionStyle();
await updateOptionStyle();
// 第一次超出边界变化方向时,Slide的动画方向更新时序问题
setTimeout(() => {
setInternalOpen(newOpen);
onOpen?.();
}, 100);
setInternalOpen(newOpen);
onOpen?.();
} else {
onClose?.();
setInternalOpen(newOpen);
Expand Down Expand Up @@ -118,10 +117,11 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>((props, ref) => {

// eslint-disable-next-line consistent-return
useEffect(() => {
const resizeCb = throttle(updateOptionStyle, 100);
if (!isMini) {
window.addEventListener('resize', updateOptionStyle);
window.addEventListener('resize', resizeCb);
return () => {
window.removeEventListener('resize', updateOptionStyle);
window.removeEventListener('resize', resizeCb);
};
}
}, []);
Expand Down Expand Up @@ -166,7 +166,12 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
exit: 167,
}}
>
<div className={clsx(`${prefixCls}-option-main`)}>{children}</div>
<div
className={clsx(`${prefixCls}-option-main`)}
ref={optionMainRef}
>
{children}
</div>
</Slide>
</div>
</Fade>
Expand Down Expand Up @@ -200,13 +205,8 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
/>
{icon || defaultIcon}
</div>
{isMini && renderOptions()}
</div>
{!isMini && (
<Portal onRootElementMouted={updateOptionStyle}>
{renderOptions()}
</Portal>
)}
<Portal onRootElementMouted={updateOptionStyle}>{renderOptions()}</Portal>
<Backdrop
open={isOpen}
invisible
Expand All @@ -225,9 +225,7 @@ const Select = React.forwardRef<HTMLDivElement, SelectProps>((props, ref) => {
Select.displayName = 'BuiSelect';
Select.defaultProps = {
defaultValue: '',
scrollContainer: () => {
return isMini ? null : document.body;
},
scrollContainer: () => null,
};

export default Select;
9 changes: 4 additions & 5 deletions packages/bui-core/src/Select/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,6 @@ export default () => {

Provide the ability to customize scroll container, which can be customized through the 'scrollContainer' attribute. Default value is '() => document.body'.
The select option container's display direction will be automatically calculated according to the scroll container.
Only support H5.

```tsx
import { Select, SelectOption, Stack } from '@bifrostui/react';
Expand Down Expand Up @@ -498,19 +497,19 @@ export default () => {
alignItems="stretch"
style={{
display: 'block',
height: '300px',
padding: '50px',
height: '150px',
padding: '10px 50px',
background: '#eee',
overflowY: 'scroll',
}}
>
<div style={{ height: '150px' }}></div>
<div style={{ height: '50px' }}></div>
<Select scrollContainer={() => ref.current}>
{options.map((item, index) => (
<SelectOption key={index} value={item.value} label={item.label} />
))}
</Select>
<div style={{ height: '500px' }}></div>
<div style={{ height: '200px' }}></div>
</Stack>
);
};
Expand Down
11 changes: 5 additions & 6 deletions packages/bui-core/src/Select/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ const options = [
];

export default () => {
const [open, setOpen] = useState<boolean>(true);
const [open, setOpen] = useState<boolean>(false);

const handleOpen = () => {
setOpen(true);
Expand Down Expand Up @@ -468,7 +468,6 @@ export default () => {

通过scrollContainer指定滚动父容器,默认是() => document.body。
指定后,下拉框的展示方向会自动根据滚动父容器进行计算。
仅支持H5。

```tsx
import { Select, SelectOption, Stack } from '@bifrostui/react';
Expand Down Expand Up @@ -498,19 +497,19 @@ export default () => {
alignItems="stretch"
style={{
display: 'block',
height: '300px',
padding: '50px',
height: '150px',
padding: '10px 50px',
background: '#eee',
overflowY: 'scroll',
}}
>
<div style={{ height: '150px' }}></div>
<div style={{ height: '50px' }}></div>
<Select scrollContainer={() => ref.current}>
{options.map((item, index) => (
<SelectOption key={index} value={item.value} label={item.label} />
))}
</Select>
<div style={{ height: '500px' }}></div>
<div style={{ height: '200px' }}></div>
</Stack>
);
};
Expand Down

0 comments on commit 55fedb1

Please sign in to comment.