Skip to content

Commit

Permalink
Merge branch 'feature' into feature
Browse files Browse the repository at this point in the history
  • Loading branch information
li-jia-nan authored Mar 20, 2024
2 parents f84bc4c + 47bd5ec commit 937acff
Show file tree
Hide file tree
Showing 20 changed files with 423 additions and 65 deletions.
2 changes: 1 addition & 1 deletion components/_util/getAllowClear.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const getAllowClear = (allowClear: AllowClear): AllowClear => {
clearIcon: <CloseCircleFilled />,
};
}

return mergedAllowClear;
};

Expand Down
15 changes: 15 additions & 0 deletions components/config-provider/__tests__/style.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Drawer from '../../drawer';
import Dropdown from '../../dropdown';
import Empty from '../../empty';
import Flex from '../../flex';
import FloatButton from '../../float-button';
import Form from '../../form';
import Image from '../../image';
import Input from '../../input';
Expand Down Expand Up @@ -1507,4 +1508,18 @@ describe('ConfigProvider support style and className props', () => {
const element = container.querySelector<HTMLSpanElement>(selectors);
expect(element).toBeTruthy();
});

it('Should FloatButton.Group closeIcon works', () => {
const { container } = render(
<ConfigProvider
floatButtonGroup={{ closeIcon: <span className="test-cp-icon">test-cp-icon</span> }}
>
<FloatButton.Group trigger="click" open>
<FloatButton />
</FloatButton.Group>
</ConfigProvider>,
);
const element = container.querySelector<HTMLSpanElement>('.test-cp-icon');
expect(element).toBeTruthy();
});
});
4 changes: 4 additions & 0 deletions components/config-provider/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { CardProps } from '../card';
import type { CollapseProps } from '../collapse';
import type { DrawerProps } from '../drawer';
import type { FlexProps } from '../flex/interface';
import type { FloatButtonGroupProps } from '../float-button/interface';
import type { FormProps } from '../form/Form';
import type { InputProps, TextAreaProps } from '../input';
import type { Locale } from '../locale';
Expand Down Expand Up @@ -124,6 +125,8 @@ export type TransferConfig = ComponentStyleConfig & Pick<TransferProps, 'selecti
export type FormConfig = ComponentStyleConfig &
Pick<FormProps, 'requiredMark' | 'colon' | 'scrollToFirstError' | 'validateMessages'>;

export type FloatButtonGroupConfig = Pick<FloatButtonGroupProps, 'closeIcon'>;

export type PaginationConfig = ComponentStyleConfig & Pick<PaginationProps, 'showSizeChanger'>;

export type SelectConfig = ComponentStyleConfig & Pick<SelectProps, 'showSearch'>;
Expand Down Expand Up @@ -167,6 +170,7 @@ export interface ConfigConsumerProps {
carousel?: ComponentStyleConfig;
cascader?: ComponentStyleConfig;
collapse?: CollapseConfig;
floatButtonGroup?: FloatButtonGroupConfig;
typography?: ComponentStyleConfig;
skeleton?: ComponentStyleConfig;
spin?: ComponentStyleConfig;
Expand Down
1 change: 1 addition & 0 deletions components/config-provider/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ const {
| dropdown | Set Dropdown common props | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
| empty | Set Empty common props | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| flex | Set Flex common props | { className?: string, style?: React.CSSProperties, vertical?: boolean } | - | 5.10.0 |
| floatButtonGroup | Set FloatButton.Group common props | { closeIcon?: React.ReactNode } | - | 5.16.0 |
| form | Set Form common props | { className?: string, style?: React.CSSProperties, validateMessages?: [ValidateMessages](/components/form/#validatemessages), requiredMark?: boolean \| `optional`, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options) } | - | requiredMark: 4.8.0; colon: 4.18.0; scrollToFirstError: 5.2.0; className: 5.7.0; style: 5.7.0 |
| image | Set Image common props | { className?: string, style?: React.CSSProperties, preview?: { closeIcon?: React.ReactNode } } | - | 5.7.0, closeIcon: 5.14.0 |
| input | Set Input common props | { autoComplete?: string, className?: string, style?: React.CSSProperties, allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 4.2.0, allowClear: 5.15.0 |
Expand Down
4 changes: 4 additions & 0 deletions components/config-provider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
DirectionType,
DrawerConfig,
FlexConfig,
FloatButtonGroupConfig,
FormConfig,
ImageConfig,
InputConfig,
Expand Down Expand Up @@ -164,6 +165,7 @@ export interface ConfigProviderProps {
slider?: ComponentStyleConfig;
breadcrumb?: ComponentStyleConfig;
menu?: MenuConfig;
floatButtonGroup?: FloatButtonGroupConfig;
checkbox?: ComponentStyleConfig;
descriptions?: ComponentStyleConfig;
empty?: ComponentStyleConfig;
Expand Down Expand Up @@ -348,6 +350,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
dropdown,
warning: warningConfig,
tour,
floatButtonGroup,
} = props;

// =================================== Context ===================================
Expand Down Expand Up @@ -443,6 +446,7 @@ const ProviderChildren: React.FC<ProviderChildrenProps> = (props) => {
dropdown,
warning: warningConfig,
tour,
floatButtonGroup,
};

const config: ConfigConsumerProps = {
Expand Down
1 change: 1 addition & 0 deletions components/config-provider/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const {
| dropdown | 设置 Dropdown 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.11.0 |
| empty | 设置 Empty 组件的通用属性 | { className?: string, style?: React.CSSProperties } | - | 5.7.0 |
| flex | 设置 Flex 组件的通用属性 | { className?: string, style?: React.CSSProperties, vertical?: boolean } | - | 5.10.0 |
| floatButtonGroup | 设置 FloatButton.Group 组件的通用属性 | { closeIcon?: React.ReactNode } | - | 5.16.0 |
| form | 设置 Form 组件的通用属性 | { className?: string, style?: React.CSSProperties, validateMessages?: [ValidateMessages](/components/form-cn#validatemessages), requiredMark?: boolean \| `optional`, colon?: boolean, scrollToFirstError?: boolean \| [Options](https://github.com/stipsan/scroll-into-view-if-needed/tree/ece40bd9143f48caf4b99503425ecb16b0ad8249#options)} | - | requiredMark: 4.8.0; colon: 4.18.0; scrollToFirstError: 5.2.0; className: 5.7.0; style: 5.7.0 |
| image | 设置 Image 组件的通用属性 | { className?: string, style?: React.CSSProperties, preview?: { closeIcon?: React.ReactNode } } | - | 5.7.0, closeIcon: 5.14.0 |
| input | 设置 Input 组件的通用属性 | { autoComplete?: string, className?: string, style?: React.CSSProperties, allowClear?: boolean \| { clearIcon?: ReactNode } } | - | 5.7.0, allowClear: 5.15.0 |
Expand Down
12 changes: 8 additions & 4 deletions components/float-button/FloatButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import useMergedState from 'rc-util/lib/hooks/useMergedState';
import { devUseWarning } from '../_util/warning';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigContext } from '../config-provider';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';
import { FloatButtonGroupProvider } from './context';
import FloatButton, { floatButtonPrefixCls } from './FloatButton';
import type { FloatButtonGroupProps, FloatButtonRef } from './interface';
import useStyle from './style';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';

const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
const {
Expand All @@ -22,7 +22,7 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
shape = 'circle',
type = 'default',
icon = <FileTextOutlined />,
closeIcon = <CloseOutlined />,
closeIcon,
description,
trigger,
children,
Expand All @@ -31,7 +31,11 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
...floatButtonProps
} = props;

const { direction, getPrefixCls } = useContext<ConfigConsumerProps>(ConfigContext);
const { direction, getPrefixCls, floatButtonGroup } =
useContext<ConfigConsumerProps>(ConfigContext);

const mergedCloseIcon = closeIcon ?? floatButtonGroup?.closeIcon ?? <CloseOutlined />;

const prefixCls = getPrefixCls(floatButtonPrefixCls, customizePrefixCls);
const rootCls = useCSSVarCls(prefixCls);
const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls, rootCls);
Expand Down Expand Up @@ -120,7 +124,7 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
ref={floatButtonRef}
type={type}
shape={shape}
icon={open ? closeIcon : icon}
icon={open ? mergedCloseIcon : icon}
description={description}
aria-label={props['aria-label']}
{...floatButtonProps}
Expand Down
1 change: 1 addition & 0 deletions components/locale/en_US.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const localeValues: Locale = {
copy: 'Copy',
copied: 'Copied',
expand: 'Expand',
collapse: 'Collapse',
},
Form: {
optional: '(optional)',
Expand Down
1 change: 1 addition & 0 deletions components/locale/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface Locale {
copy?: any;
copied?: any;
expand?: any;
collapse?: any;
};
Form?: {
optional?: string;
Expand Down
1 change: 1 addition & 0 deletions components/locale/zh_CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const localeValues: Locale = {
copy: '复制',
copied: '复制成功',
expand: '展开',
collapse: '收起',
},
Form: {
optional: '(可选)',
Expand Down
20 changes: 11 additions & 9 deletions components/typography/Base/Ellipsis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,11 @@ export interface EllipsisProps {
rows: number;
children: (
cutChildren: React.ReactNode[],
/** Tell current `cutChildren` is in ellipsis */
inEllipsis: boolean,
/** Tell current `text` is exceed the `rows` which can be ellipsis */
canEllipsis: boolean,
) => React.ReactNode;
onEllipsis: (isEllipsis: boolean) => void;
expanded: boolean;
/**
* Mark for misc update. Which will not affect ellipsis content length.
* e.g. tooltip content update.
Expand All @@ -131,13 +130,14 @@ const lineClipStyle: React.CSSProperties = {
};

export default function EllipsisMeasure(props: EllipsisProps) {
const { enableMeasure, width, text, children, rows, miscDeps, onEllipsis } = props;
const { enableMeasure, width, text, children, rows, expanded, miscDeps, onEllipsis } = props;

const nodeList = React.useMemo(() => toArray(text), [text]);
const nodeLen = React.useMemo(() => getNodesLen(nodeList), [text]);

// ========================= Full Content =========================
const fullContent = React.useMemo(() => children(nodeList, false, false), [text]);
// Used for measure only, which means it's always render as no need ellipsis
const fullContent = React.useMemo(() => children(nodeList, false), [text]);

// ========================= Cut Content ==========================
const [ellipsisCutIndex, setEllipsisCutIndex] = React.useState<[number, number] | null>(null);
Expand All @@ -150,6 +150,7 @@ export default function EllipsisMeasure(props: EllipsisProps) {
const descRowsEllipsisRef = React.useRef<MeasureTextRef>(null);
const symbolRowEllipsisRef = React.useRef<MeasureTextRef>(null);

const [canEllipsis, setCanEllipsis] = React.useState(false);
const [needEllipsis, setNeedEllipsis] = React.useState(STATUS_MEASURE_NONE);
const [ellipsisHeight, setEllipsisHeight] = React.useState(0);

Expand All @@ -169,6 +170,7 @@ export default function EllipsisMeasure(props: EllipsisProps) {

setNeedEllipsis(isOverflow ? STATUS_MEASURE_NEED_ELLIPSIS : STATUS_MEASURE_NO_NEED_ELLIPSIS);
setEllipsisCutIndex(isOverflow ? [0, nodeLen] : null);
setCanEllipsis(isOverflow);

// Get the basic height of ellipsis rows
const baseRowsEllipsisHeight = needEllipsisRef.current?.getHeight() || 0;
Expand Down Expand Up @@ -218,7 +220,7 @@ export default function EllipsisMeasure(props: EllipsisProps) {
!ellipsisCutIndex ||
ellipsisCutIndex[0] !== ellipsisCutIndex[1]
) {
const content = children(nodeList, false, false);
const content = children(nodeList, false);

// Limit the max line count to avoid scrollbar blink
// https://github.com/ant-design/ant-design/issues/42958
Expand All @@ -241,8 +243,8 @@ export default function EllipsisMeasure(props: EllipsisProps) {
return content;
}

return children(sliceNodes(nodeList, ellipsisCutIndex[0]), true, true);
}, [needEllipsis, ellipsisCutIndex, nodeList, ...miscDeps]);
return children(expanded ? nodeList : sliceNodes(nodeList, ellipsisCutIndex[0]), canEllipsis);
}, [expanded, needEllipsis, ellipsisCutIndex, nodeList, ...miscDeps]);

// ============================ Render ============================
const measureStyle: React.CSSProperties = {
Expand Down Expand Up @@ -293,7 +295,7 @@ export default function EllipsisMeasure(props: EllipsisProps) {
}}
ref={symbolRowEllipsisRef}
>
{children([], true, true)}
{children([], true)}
</MeasureText>
</>
)}
Expand All @@ -309,7 +311,7 @@ export default function EllipsisMeasure(props: EllipsisProps) {
}}
ref={cutMidRef}
>
{children(sliceNodes(nodeList, cutMidIndex), true, true)}
{children(sliceNodes(nodeList, cutMidIndex), true)}
</MeasureText>
)}
</>
Expand Down
56 changes: 29 additions & 27 deletions components/typography/Base/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,12 @@ interface EditConfig {

export interface EllipsisConfig {
rows?: number;
expandable?: boolean;
expandable?: boolean | 'collapsible';
suffix?: string;
symbol?: React.ReactNode;
onExpand?: React.MouseEventHandler<HTMLElement>;
symbol?: React.ReactNode | ((expanded: boolean) => React.ReactNode);
defaultExpanded?: boolean;
expanded?: boolean;
onExpand?: (e: React.MouseEvent<HTMLElement, MouseEvent>, info: { expanded: boolean }) => void;
onEllipsis?: (ellipsis: boolean) => void;
tooltip?: React.ReactNode | TooltipProps;
}
Expand Down Expand Up @@ -215,15 +217,19 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
const [isLineClampSupport, setIsLineClampSupport] = React.useState(false);
const [isTextOverflowSupport, setIsTextOverflowSupport] = React.useState(false);

const [expanded, setExpanded] = React.useState(false);
const [isJsEllipsis, setIsJsEllipsis] = React.useState(false);
const [isNativeEllipsis, setIsNativeEllipsis] = React.useState(false);
const [isNativeVisible, setIsNativeVisible] = React.useState(true);
const [enableEllipsis, ellipsisConfig] = useMergedConfig<EllipsisConfig>(ellipsis, {
expandable: false,
symbol: (isExpanded) => (isExpanded ? textLocale?.collapse : textLocale?.expand),
});
const [expanded, setExpanded] = useMergedState(ellipsisConfig.defaultExpanded || false, {
value: ellipsisConfig.expanded,
});

const mergedEnableEllipsis = enableEllipsis && !expanded;
const mergedEnableEllipsis =
enableEllipsis && (!expanded || ellipsisConfig.expandable === 'collapsible');

// Shared prop to reduce bundle size
const { rows = 1 } = ellipsisConfig;
Expand Down Expand Up @@ -267,9 +273,9 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
const cssLineClamp = mergedEnableEllipsis && rows > 1 && cssEllipsis;

// >>>>> Expand
const onExpandClick: React.MouseEventHandler<HTMLElement> = (e) => {
setExpanded(true);
ellipsisConfig.onExpand?.(e);
const onExpandClick: EllipsisConfig['onExpand'] = (e, info) => {
setExpanded(info.expanded);
ellipsisConfig.onExpand?.(e, info);
};

const [ellipsisWidth, setEllipsisWidth] = React.useState(0);
Expand Down Expand Up @@ -389,22 +395,16 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
const { expandable, symbol } = ellipsisConfig;

if (!expandable) return null;

let expandContent: React.ReactNode;
if (symbol) {
expandContent = symbol;
} else {
expandContent = textLocale?.expand;
}
if (expanded && expandable !== 'collapsible') return null;

return (
<a
key="expand"
className={`${prefixCls}-expand`}
onClick={onExpandClick}
aria-label={textLocale?.expand}
className={`${prefixCls}-${expanded ? 'collapse' : 'expand'}`}
onClick={(e) => onExpandClick(e, { expanded: !expanded })}
aria-label={expanded ? textLocale.collapse : textLocale?.expand}
>
{expandContent}
{typeof symbol === 'function' ? symbol(expanded) : symbol}
</a>
);
};
Expand Down Expand Up @@ -451,20 +451,21 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
);
};

const renderOperations = (renderExpanded: boolean) => [
renderExpanded && renderExpand(),
const renderOperations = (canEllipsis: boolean) => [
// (renderExpanded || ellipsisConfig.collapsible) && renderExpand(),
canEllipsis && renderExpand(),
renderEdit(),
renderCopy(),
];

const renderEllipsis = (needEllipsis: boolean) => [
needEllipsis && (
const renderEllipsis = (canEllipsis: boolean) => [
canEllipsis && !expanded && (
<span aria-hidden key="ellipsis">
{ELLIPSIS_STR}
</span>
),
ellipsisConfig.suffix,
renderOperations(needEllipsis),
renderOperations(canEllipsis),
];

return (
Expand Down Expand Up @@ -506,11 +507,12 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
rows={rows}
width={ellipsisWidth}
onEllipsis={onJsEllipsis}
expanded={expanded}
miscDeps={[copied, expanded]}
>
{(node, needEllipsis) => {
{(node, canEllipsis) => {
let renderNode: React.ReactNode = node;
if (node.length && needEllipsis && topAriaLabel) {
if (node.length && canEllipsis && !expanded && topAriaLabel) {
renderNode = (
<span key="show-content" aria-hidden>
{renderNode}
Expand All @@ -522,7 +524,7 @@ const Base = React.forwardRef<HTMLElement, BlockProps>((props, ref) => {
props,
<>
{renderNode}
{renderEllipsis(needEllipsis)}
{renderEllipsis(canEllipsis)}
</>,
);

Expand Down
Loading

0 comments on commit 937acff

Please sign in to comment.