Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Overflow): add prefix prop #48

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/fill-width.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const Demo = () => {
renderItem={renderItem}
renderRest={renderRest}
maxCount={responsive ? 'responsive' : 6}
prefix={<span>Foobar</span>}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个和 overflow 没有关系,在 rc-select 层同级添加就行了

suffix={
<div style={{ position: 'relative', maxWidth: '100%' }}>
<input
Expand Down
82 changes: 55 additions & 27 deletions src/Overflow.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as React from 'react';
import { useState, useMemo, useCallback } from 'react';
import classNames from 'classnames';
import ResizeObserver from 'rc-resize-observer';
import useLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import * as React from 'react';
import { useCallback, useMemo, useState } from 'react';
import Item from './Item';
import useEffectState, { useBatcher } from './hooks/useEffectState';
import type { ComponentType } from './RawItem';
import RawItem from './RawItem';
import { OverflowContext } from './context';
import useEffectState, { useBatcher } from './hooks/useEffectState';

const RESPONSIVE = 'responsive' as const;
const INVALIDATE = 'invalidate' as const;
Expand All @@ -16,7 +16,7 @@ export { OverflowContext } from './context';

export type { ComponentType } from './RawItem';

export interface OverflowProps<ItemType> extends React.HTMLAttributes<any> {
export interface OverflowProps<ItemType> extends Omit<React.HTMLAttributes<any>, 'prefix'> {
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
Expand All @@ -33,6 +33,7 @@ export interface OverflowProps<ItemType> extends React.HTMLAttributes<any> {
| ((omittedItems: ItemType[]) => React.ReactNode);
/** @private Do not use in your production. Render raw node that need wrap Item by developer self */
renderRawRest?: (omittedItems: ItemType[]) => React.ReactElement;
prefix?: React.ReactNode;
suffix?: React.ReactNode;
component?: ComponentType;
itemComponent?: ComponentType;
Expand Down Expand Up @@ -65,6 +66,7 @@ function Overflow<ItemType = any>(
maxCount,
renderRest,
renderRawRest,
prefix,
suffix,
component: Component = 'div',
itemComponent,
Expand Down Expand Up @@ -96,6 +98,11 @@ function Overflow<ItemType = any>(
0,
);

const [prefixWidth, setPrefixWidth] = useEffectState<number>(
notifyEffectUpdate,
0,
);

const [suffixWidth, setSuffixWidth] = useEffectState<number>(
notifyEffectUpdate,
0,
Expand Down Expand Up @@ -223,6 +230,10 @@ function Overflow<ItemType = any>(
setPrevRestWidth(restWidth);
}

function registerPrefixSize(_: React.Key, width: number | null) {
setPrefixWidth(width!);
}

function registerSuffixSize(_: React.Key, width: number | null) {
setSuffixWidth(width!);
}
Expand All @@ -238,7 +249,7 @@ function Overflow<ItemType = any>(
typeof mergedRestWidth === 'number' &&
mergedData
) {
let totalWidth = suffixWidth;
let totalWidth = prefixWidth + suffixWidth;

const len = mergedData.length;
const lastIndex = len - 1;
Expand Down Expand Up @@ -286,14 +297,15 @@ function Overflow<ItemType = any>(
}
}

if (suffix && getItemWidth(0) + suffixWidth > mergedContainerWidth) {
if (suffix && getItemWidth(0) + suffixWidth + prefixWidth > mergedContainerWidth) {
setSuffixFixedStart(null);
}
}
}, [
mergedContainerWidth,
itemWidths,
restWidth,
prefixWidth,
suffixWidth,
getKey,
mergedData,
Expand Down Expand Up @@ -366,26 +378,26 @@ function Overflow<ItemType = any>(

const mergedRenderRest = renderRest || defaultRenderRest;

const restNode = renderRawRest ? (
<OverflowContext.Provider
value={{
...itemSharedProps,
...restContextProps,
}}
>
{renderRawRest(omittedItems)}
</OverflowContext.Provider>
) : (
<Item
{...itemSharedProps}
// When not show, order should be the last
{...restContextProps}
>
{typeof mergedRenderRest === 'function'
? mergedRenderRest(omittedItems)
: mergedRenderRest}
</Item>
);
const restNode = renderRawRest ? (
<OverflowContext.Provider
value={{
...itemSharedProps,
...restContextProps,
}}
>
{renderRawRest(omittedItems)}
</OverflowContext.Provider>
) : (
<Item
{...itemSharedProps}
// When not show, order should be the last
{...restContextProps}
>
{typeof mergedRenderRest === 'function'
? mergedRenderRest(omittedItems)
: mergedRenderRest}
</Item>
);

const overflowNode = (
<Component
Expand All @@ -394,6 +406,20 @@ function Overflow<ItemType = any>(
ref={ref}
{...restProps}
>
{/* Prefix Node */}
{prefix && (
<Item
{...itemSharedProps}
responsive={isResponsive}
responsiveDisabled={!shouldResponsive}
order={mergedDisplayCount}
className={`${itemPrefixCls}-prefix`}
registerSize={registerPrefixSize}
display
>
{prefix}
</Item>
)}
{mergedData.map(internalRenderItemNode)}

{/* Rest Count Item */}
Expand Down Expand Up @@ -421,7 +447,9 @@ function Overflow<ItemType = any>(
<ResizeObserver onResize={onOverflowResize} disabled={!shouldResponsive}>
{overflowNode}
</ResizeObserver>
) : overflowNode;
) : (
overflowNode
);
}

const ForwardOverflow = React.forwardRef(Overflow);
Expand Down
Loading