mirror of
https://github.com/ant-design/ant-design.git
synced 2025-08-06 16:06:28 +08:00
Merge branch 'feature' into feat-splitPanel
This commit is contained in:
commit
03c8074958
@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { BgColorsOutlined, SmileOutlined } from '@ant-design/icons';
|
||||
import { FloatButton } from 'antd';
|
||||
import { useTheme } from 'antd-style';
|
||||
import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons';
|
||||
// import { Motion } from 'antd-token-previewer/es/icons';
|
||||
import { FormattedMessage, useLocation } from 'dumi';
|
||||
@ -20,7 +19,6 @@ export interface ThemeSwitchProps {
|
||||
|
||||
const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
|
||||
const { value = ['light'], onChange } = props;
|
||||
const token = useTheme();
|
||||
const { pathname, search } = useLocation();
|
||||
|
||||
// const isMotionOff = value.includes('motion-off');
|
||||
@ -38,7 +36,7 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = (props) => {
|
||||
>
|
||||
<Link
|
||||
to={getLocalizedPathname('/theme-editor', isZhCN(pathname), search)}
|
||||
style={{ display: 'block', marginBottom: token.margin }}
|
||||
style={{ display: 'block' }}
|
||||
>
|
||||
<FloatButton
|
||||
icon={<BgColorsOutlined />}
|
||||
|
@ -16,6 +16,20 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.20.2
|
||||
|
||||
`2024-08-19`
|
||||
|
||||
- 💄 Fix the suffix style problem of InputNumber without control. [#50450](https://github.com/ant-design/ant-design/pull/50450) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🆕 Form `rule.message` supports skipping variable substitution through `\\${}`. [#50412](https://github.com/ant-design/ant-design/pull/50412) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 Fixed the issue where the rounded corners of the trigger element are missing when the FloatButton component has shape="square" and in menu mode when the menu pops up. [#50408](https://github.com/ant-design/ant-design/pull/50408) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 Fixed the problem that Upload.Dragger does not work when dragging and dropping upload folders. [#50394](https://github.com/ant-design/ant-design/pull/50394) [@huiliangShen](https://github.com/huiliangShen)
|
||||
- 🐞 Fixed the issue where the arrow icon disappears after hovering when Select specifies `getPopcontainer={node=node.parentNode}`. [#50382](https://github.com/ant-design/ant-design/pull/50382) [@afc163](https://github.com/afc163)
|
||||
- 🐞 Fixed the arrow misalignment error when Popover sets the `arrow.pointAtCenter` property. [#50260](https://github.com/ant-design/ant-design/pull/50260) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 📖 Transfer adds Russian and Ukrainian localization copy. [#50429](https://github.com/ant-design/ant-design/pull/50429) [@alexlag](https://github.com/alexlag)
|
||||
- TypeScript
|
||||
- 🤖 Roll back the Table partial generic constraint object to any to reduce break changes caused by [#50351](https://github.com/ant-design/ant-design/pull/50351). [#50372](https://github.com/ant-design/ant-design/pull/50372) [@crazyair](https://github.com/crazyair)
|
||||
|
||||
## 5.20.1
|
||||
|
||||
`2024-08-11`
|
||||
|
@ -15,6 +15,20 @@ tag: vVERSION
|
||||
|
||||
---
|
||||
|
||||
## 5.20.2
|
||||
|
||||
`2024-08-19`
|
||||
|
||||
- 💄 修复 InputNumber 没有控件的后缀样式问题。[#50450](https://github.com/ant-design/ant-design/pull/50450) [@coding-ice](https://github.com/coding-ice)
|
||||
- 🆕 Form `rule.message` 支持通过 `\\${}` 跳过变量替换。[#50412](https://github.com/ant-design/ant-design/pull/50412) [@zombieJ](https://github.com/zombieJ)
|
||||
- 🐞 修复了 FloatButton 组件当 shape=“square” 时,并且在菜单模式下,菜单弹出时 trigger 元素圆角缺失的问题。[#50408](https://github.com/ant-design/ant-design/pull/50408) [@li-jia-nan](https://github.com/li-jia-nan)
|
||||
- 🐞 修复 Upload.Dragger 拖拽上传文件夹时不工作问题。[#50394](https://github.com/ant-design/ant-design/pull/50394) [@huiliangShen](https://github.com/huiliangShen)
|
||||
- 🐞 修复 Select 指定 `getPopcontainer={node=node.parentNode}` 时箭头图标 hover 后会消失的问题。[#50382](https://github.com/ant-design/ant-design/pull/50382) [@afc163](https://github.com/afc163)
|
||||
- 🐞 修复 Popover 设置 `arrow.pointAtCenter` 属性时箭头未对齐错误。[#50260](https://github.com/ant-design/ant-design/pull/50260) [@Wxh16144](https://github.com/Wxh16144)
|
||||
- 📖 Transfer 补充俄罗斯语和乌克兰语本地化文案。[#50429](https://github.com/ant-design/ant-design/pull/50429) [@alexlag](https://github.com/alexlag)
|
||||
- TypeScript
|
||||
- 🤖 将 Table 部分泛型约束 object 回滚为 any,以减少 [#50351](https://github.com/ant-design/ant-design/pull/50351) 造成的 break change。[#50372](https://github.com/ant-design/ant-design/pull/50372) [@crazyair](https://github.com/crazyair)
|
||||
|
||||
## 5.20.1
|
||||
|
||||
`2024-08-11`
|
||||
|
@ -34,12 +34,15 @@ function doMouseMove(
|
||||
});
|
||||
|
||||
fireEvent(ele, mouseDown);
|
||||
// Drag
|
||||
const mouseMove: any = new Event('mousemove');
|
||||
mouseMove.pageX = end;
|
||||
mouseMove.pageY = end;
|
||||
|
||||
fireEvent(document, mouseMove);
|
||||
// Drag
|
||||
if (start !== end) {
|
||||
const mouseMove: any = new Event('mousemove');
|
||||
mouseMove.pageX = end;
|
||||
mouseMove.pageY = end;
|
||||
|
||||
fireEvent(document, mouseMove);
|
||||
}
|
||||
|
||||
const mouseUp = createEvent.mouseUp(document);
|
||||
fireEvent(document, mouseUp);
|
||||
@ -848,4 +851,32 @@ describe('ColorPicker', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('onChangeComplete with default empty color should not be alpha', async () => {
|
||||
const spyRect = spyElementPrototypes(HTMLElement, {
|
||||
getBoundingClientRect: () => ({
|
||||
x: 0,
|
||||
y: 100,
|
||||
width: 100,
|
||||
height: 100,
|
||||
}),
|
||||
});
|
||||
|
||||
const handleChangeComplete = jest.fn();
|
||||
const { container } = render(<ColorPicker open onChangeComplete={handleChangeComplete} />);
|
||||
|
||||
// Move
|
||||
doMouseMove(container, 50, 50);
|
||||
expect(handleChangeComplete).toHaveBeenCalledTimes(1);
|
||||
|
||||
const color = handleChangeComplete.mock.calls[0][0];
|
||||
expect(color.toRgb()).toEqual({
|
||||
r: 255,
|
||||
g: 128,
|
||||
b: 128,
|
||||
a: 1,
|
||||
});
|
||||
|
||||
spyRect.mockRestore();
|
||||
});
|
||||
});
|
||||
|
@ -17,6 +17,11 @@ const components = {
|
||||
slider: ColorSlider,
|
||||
};
|
||||
|
||||
type Info = {
|
||||
type?: 'hue' | 'alpha';
|
||||
value?: number;
|
||||
};
|
||||
|
||||
const PanelPicker: FC = () => {
|
||||
const panelPickerContext = useContext(PanelPickerContext);
|
||||
|
||||
@ -81,32 +86,10 @@ const PanelPicker: FC = () => {
|
||||
}, [value, activeIndex, isSingle, lockedColor, gradientDragging]);
|
||||
|
||||
// ============================ Change ============================
|
||||
const fillColor = (nextColor: AggregationColor) => {
|
||||
if (mode === 'single') {
|
||||
return nextColor;
|
||||
}
|
||||
|
||||
const nextColors = [...colors];
|
||||
nextColors[activeIndex] = {
|
||||
...nextColors[activeIndex],
|
||||
color: nextColor,
|
||||
};
|
||||
|
||||
return new AggregationColor(nextColors);
|
||||
};
|
||||
|
||||
const onInternalChange = (
|
||||
colorValue: AggregationColor | Color,
|
||||
fromPicker?: boolean,
|
||||
info?: {
|
||||
type?: 'hue' | 'alpha';
|
||||
value?: number;
|
||||
},
|
||||
) => {
|
||||
const nextColor = generateColor(colorValue);
|
||||
|
||||
let submitColor = nextColor;
|
||||
const fillColor = (nextColor: AggregationColor | Color, info?: Info) => {
|
||||
let submitColor = generateColor(nextColor);
|
||||
|
||||
// Fill alpha color to 100% if origin is cleared color
|
||||
if (value.cleared) {
|
||||
const rgb = submitColor.toRgb();
|
||||
|
||||
@ -125,11 +108,29 @@ const PanelPicker: FC = () => {
|
||||
}
|
||||
}
|
||||
|
||||
onChange(fillColor(submitColor), fromPicker);
|
||||
if (mode === 'single') {
|
||||
return submitColor;
|
||||
}
|
||||
|
||||
const nextColors = [...colors];
|
||||
nextColors[activeIndex] = {
|
||||
...nextColors[activeIndex],
|
||||
color: submitColor,
|
||||
};
|
||||
|
||||
return new AggregationColor(nextColors);
|
||||
};
|
||||
|
||||
const onInternalChangeComplete = (nextColor: AggregationColor) => {
|
||||
onChangeComplete(fillColor(nextColor));
|
||||
const onInternalChange = (
|
||||
colorValue: AggregationColor | Color,
|
||||
fromPicker?: boolean,
|
||||
info?: Info,
|
||||
) => {
|
||||
onChange(fillColor(colorValue, info), fromPicker);
|
||||
};
|
||||
|
||||
const onInternalChangeComplete = (nextColor: Color, info?: Info) => {
|
||||
onChangeComplete(fillColor(nextColor, info));
|
||||
};
|
||||
|
||||
// ============================ Render ============================
|
||||
@ -170,8 +171,8 @@ const PanelPicker: FC = () => {
|
||||
onChange={(colorValue, info) => {
|
||||
onInternalChange(colorValue, true, info);
|
||||
}}
|
||||
onChangeComplete={(colorValue) => {
|
||||
onInternalChangeComplete(generateColor(colorValue));
|
||||
onChangeComplete={(colorValue, info) => {
|
||||
onInternalChangeComplete(colorValue, info);
|
||||
}}
|
||||
components={components}
|
||||
/>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React, { memo, useCallback, useContext, useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import CloseOutlined from '@ant-design/icons/CloseOutlined';
|
||||
import FileTextOutlined from '@ant-design/icons/FileTextOutlined';
|
||||
import classNames from 'classnames';
|
||||
import CSSMotion from 'rc-motion';
|
||||
import { useEvent } from 'rc-util';
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
|
||||
import { useZIndex } from '../_util/hooks/useZIndex';
|
||||
@ -12,16 +13,17 @@ 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 type { FloatButtonGroupProps } from './interface';
|
||||
import useStyle from './style';
|
||||
|
||||
const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
|
||||
const FloatButtonGroup: React.FC<Readonly<FloatButtonGroupProps>> = (props) => {
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
className,
|
||||
style,
|
||||
shape = 'circle',
|
||||
type = 'default',
|
||||
placement = 'top',
|
||||
icon = <FileTextOutlined />,
|
||||
closeIcon,
|
||||
description,
|
||||
@ -29,23 +31,29 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
|
||||
children,
|
||||
onOpenChange,
|
||||
open: customOpen,
|
||||
onClick: onTriggerButtonClick,
|
||||
...floatButtonProps
|
||||
} = props;
|
||||
|
||||
const { direction, getPrefixCls, floatButtonGroup } =
|
||||
useContext<ConfigConsumerProps>(ConfigContext);
|
||||
React.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);
|
||||
|
||||
const groupPrefixCls = `${prefixCls}-group`;
|
||||
|
||||
const isMenuMode = trigger && ['click', 'hover'].includes(trigger);
|
||||
const isValidPlacement = placement && ['top', 'left', 'right', 'bottom'].includes(placement);
|
||||
|
||||
const groupCls = classNames(groupPrefixCls, hashId, cssVarCls, rootCls, className, {
|
||||
[`${groupPrefixCls}-rtl`]: direction === 'rtl',
|
||||
[`${groupPrefixCls}-${shape}`]: shape,
|
||||
[`${groupPrefixCls}-${shape}-shadow`]: !trigger,
|
||||
[`${groupPrefixCls}-${shape}-shadow`]: !isMenuMode,
|
||||
[`${groupPrefixCls}-${placement}`]: isMenuMode && isValidPlacement, // 只有菜单模式才支持弹出方向
|
||||
});
|
||||
|
||||
// ============================ zIndex ============================
|
||||
@ -59,53 +67,53 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
|
||||
|
||||
const floatButtonGroupRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const floatButtonRef = React.useRef<FloatButtonRef['nativeElement']>(null);
|
||||
// ========================== Open ==========================
|
||||
const hoverTrigger = trigger === 'hover';
|
||||
const clickTrigger = trigger === 'click';
|
||||
|
||||
const hoverAction = React.useMemo<React.DOMAttributes<HTMLDivElement>>(() => {
|
||||
const hoverTypeAction = {
|
||||
onMouseEnter() {
|
||||
setOpen(true);
|
||||
onOpenChange?.(true);
|
||||
},
|
||||
onMouseLeave() {
|
||||
setOpen(false);
|
||||
onOpenChange?.(false);
|
||||
},
|
||||
};
|
||||
return trigger === 'hover' ? hoverTypeAction : {};
|
||||
}, [trigger]);
|
||||
const triggerOpen = useEvent((nextOpen: boolean) => {
|
||||
if (open !== nextOpen) {
|
||||
setOpen(nextOpen);
|
||||
onOpenChange?.(nextOpen);
|
||||
}
|
||||
});
|
||||
|
||||
const handleOpenChange = () => {
|
||||
setOpen((prevState) => {
|
||||
onOpenChange?.(!prevState);
|
||||
return !prevState;
|
||||
});
|
||||
// ===================== Trigger: Hover =====================
|
||||
const onMouseEnter: React.MouseEventHandler<HTMLDivElement> = () => {
|
||||
if (hoverTrigger) {
|
||||
triggerOpen(true);
|
||||
}
|
||||
};
|
||||
|
||||
const onClick = useCallback(
|
||||
(e: MouseEvent) => {
|
||||
if (floatButtonGroupRef.current?.contains(e.target as Node)) {
|
||||
if (floatButtonRef.current?.contains(e.target as Node)) {
|
||||
handleOpenChange();
|
||||
}
|
||||
return;
|
||||
}
|
||||
setOpen(false);
|
||||
onOpenChange?.(false);
|
||||
},
|
||||
[trigger],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (trigger === 'click') {
|
||||
document.addEventListener('click', onClick);
|
||||
return () => {
|
||||
document.removeEventListener('click', onClick);
|
||||
};
|
||||
const onMouseLeave: React.MouseEventHandler<HTMLDivElement> = () => {
|
||||
if (hoverTrigger) {
|
||||
triggerOpen(false);
|
||||
}
|
||||
}, [trigger]);
|
||||
};
|
||||
|
||||
// =================== Warning =====================
|
||||
// ===================== Trigger: Click =====================
|
||||
const onInternalTriggerButtonClick: FloatButtonGroupProps['onClick'] = (e) => {
|
||||
if (clickTrigger) {
|
||||
triggerOpen(!open);
|
||||
}
|
||||
onTriggerButtonClick?.(e);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (clickTrigger) {
|
||||
const onDocClick = (e: MouseEvent) => {
|
||||
// Skip if click on the group
|
||||
if (floatButtonGroupRef.current?.contains(e.target as Node)) {
|
||||
return;
|
||||
}
|
||||
triggerOpen(false);
|
||||
};
|
||||
document.addEventListener('click', onDocClick, { capture: true });
|
||||
return () => document.removeEventListener('click', onDocClick, { capture: true });
|
||||
}
|
||||
}, [clickTrigger]);
|
||||
|
||||
// ======================== Warning =========================
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const warning = devUseWarning('FloatButton.Group');
|
||||
|
||||
@ -116,10 +124,18 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
|
||||
);
|
||||
}
|
||||
|
||||
// ========================= Render =========================
|
||||
return wrapCSSVar(
|
||||
<FloatButtonGroupProvider value={shape}>
|
||||
<div ref={floatButtonGroupRef} className={groupCls} style={mergedStyle} {...hoverAction}>
|
||||
{trigger && ['click', 'hover'].includes(trigger) ? (
|
||||
<div
|
||||
ref={floatButtonGroupRef}
|
||||
className={groupCls}
|
||||
style={mergedStyle}
|
||||
// Hover trigger
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
>
|
||||
{isMenuMode ? (
|
||||
<>
|
||||
<CSSMotion visible={open} motionName={`${groupPrefixCls}-wrap`}>
|
||||
{({ className: motionClassName }) => (
|
||||
@ -127,12 +143,12 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
|
||||
)}
|
||||
</CSSMotion>
|
||||
<FloatButton
|
||||
ref={floatButtonRef}
|
||||
type={type}
|
||||
icon={open ? mergedCloseIcon : icon}
|
||||
description={description}
|
||||
aria-label={props['aria-label']}
|
||||
className={`${groupPrefixCls}-trigger`}
|
||||
onClick={onInternalTriggerButtonClick}
|
||||
{...floatButtonProps}
|
||||
/>
|
||||
</>
|
||||
@ -144,4 +160,4 @@ const FloatButtonGroup: React.FC<FloatButtonGroupProps> = (props) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(FloatButtonGroup);
|
||||
export default FloatButtonGroup;
|
||||
|
@ -574,7 +574,7 @@ Array [
|
||||
</span>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="inset-inline-end: 24px;"
|
||||
>
|
||||
<div
|
||||
@ -737,7 +737,7 @@ Array [
|
||||
</button>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-square"
|
||||
class="ant-float-btn-group ant-float-btn-group-square ant-float-btn-group-top"
|
||||
style="inset-inline-end: 88px;"
|
||||
>
|
||||
<div
|
||||
@ -1292,7 +1292,7 @@ exports[`renders components/float-button/demo/group.tsx extend context correctly
|
||||
exports[`renders components/float-button/demo/group-menu.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="inset-inline-end: 24px;"
|
||||
>
|
||||
<button
|
||||
@ -1333,7 +1333,7 @@ Array [
|
||||
</button>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="inset-inline-end: 94px;"
|
||||
>
|
||||
<button
|
||||
@ -1378,6 +1378,184 @@ Array [
|
||||
|
||||
exports[`renders components/float-button/demo/group-menu.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/float-button/demo/placement.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-flex ant-flex-align-center ant-flex-justify-space-evenly"
|
||||
style="width: 100%; height: 100vh; overflow: hidden; position: relative;"
|
||||
>
|
||||
<div
|
||||
style="width: 100px; height: 100px; position: relative;"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="position: absolute; inset-inline-end: 30px; bottom: 80px;"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-right"
|
||||
style="position: absolute; inset-inline-end: -20px; bottom: 30px;"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-bottom"
|
||||
style="position: absolute; inset-inline-end: 30px; bottom: -20px;"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-left"
|
||||
style="position: absolute; inset-inline-end: 80px; bottom: 30px;"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/float-button/demo/placement.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/float-button/demo/render-panel.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
style="display: flex; column-gap: 16px; align-items: center;"
|
||||
@ -1614,7 +1792,7 @@ exports[`renders components/float-button/demo/render-panel.tsx extend context co
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-pure ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-pure ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-group-wrap-appear ant-float-btn-group-wrap-appear-start ant-float-btn-group-wrap ant-float-btn-group-wrap"
|
||||
|
@ -526,7 +526,7 @@ Array [
|
||||
</span>
|
||||
</button>,
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="inset-inline-end:24px"
|
||||
>
|
||||
<div
|
||||
@ -689,7 +689,7 @@ Array [
|
||||
</button>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-square"
|
||||
class="ant-float-btn-group ant-float-btn-group-square ant-float-btn-group-top"
|
||||
style="inset-inline-end:88px"
|
||||
>
|
||||
<div
|
||||
@ -1238,7 +1238,7 @@ Array [
|
||||
exports[`renders components/float-button/demo/group-menu.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="inset-inline-end:24px"
|
||||
>
|
||||
<button
|
||||
@ -1279,7 +1279,7 @@ Array [
|
||||
</button>
|
||||
</div>,
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="inset-inline-end:94px"
|
||||
>
|
||||
<button
|
||||
@ -1322,6 +1322,182 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/float-button/demo/placement.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-flex ant-flex-align-center ant-flex-justify-space-evenly"
|
||||
style="width:100%;height:100vh;overflow:hidden;position:relative"
|
||||
>
|
||||
<div
|
||||
style="width:100px;height:100px;position:relative"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
style="position:absolute;inset-inline-end:30px;bottom:80px"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="up"
|
||||
class="anticon anticon-up"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="up"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M890.5 755.3L537.9 269.2c-12.8-17.6-39-17.6-51.7 0L133.5 755.3A8 8 0 00140 768h75c5.1 0 9.9-2.5 12.9-6.6L512 369.8l284.1 391.6c3 4.1 7.8 6.6 12.9 6.6h75c6.5 0 10.3-7.4 6.5-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-right"
|
||||
style="position:absolute;inset-inline-end:-20px;bottom:30px"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-bottom"
|
||||
style="position:absolute;inset-inline-end:30px;bottom:-20px"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="down"
|
||||
class="anticon anticon-down"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="down"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-group-circle ant-float-btn-group-left"
|
||||
style="position:absolute;inset-inline-end:80px;bottom:30px"
|
||||
>
|
||||
<button
|
||||
class="ant-float-btn ant-float-btn-group-trigger ant-float-btn-default ant-float-btn-circle"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-body"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-content"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-icon"
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/float-button/demo/render-panel.tsx correctly 1`] = `
|
||||
<div
|
||||
style="display:flex;column-gap:16px;align-items:center"
|
||||
@ -1558,7 +1734,7 @@ exports[`renders components/float-button/demo/render-panel.tsx correctly 1`] = `
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="ant-float-btn-group ant-float-btn-pure ant-float-btn-group-circle"
|
||||
class="ant-float-btn-group ant-float-btn-pure ant-float-btn-group-circle ant-float-btn-group-top"
|
||||
>
|
||||
<div
|
||||
class="ant-float-btn-group-wrap"
|
||||
|
@ -120,4 +120,16 @@ describe('FloatButtonGroup', () => {
|
||||
|
||||
expect(container.querySelector('.ant-badge')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('FloatButton.Group should support placement', () => {
|
||||
(['bottom', 'left', 'right', 'top'] as const).forEach((placement) => {
|
||||
const { container } = render(
|
||||
<FloatButton.Group placement={placement} trigger="click" open>
|
||||
<FloatButton />
|
||||
</FloatButton.Group>,
|
||||
);
|
||||
const element = container.querySelector<HTMLDivElement>('.ant-float-btn-group');
|
||||
expect(element).toHaveClass(`ant-float-btn-group-${placement}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
7
components/float-button/demo/placement.md
Normal file
7
components/float-button/demo/placement.md
Normal file
@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
自定义弹出位置,提供了四个预设值:`top`、`right`、`bottom`、`left`,默认值为 `top`。
|
||||
|
||||
## en-US
|
||||
|
||||
Customize animation placement, providing four preset placement: `top`, `right`, `bottom`, `left`, the `top` position by default.
|
74
components/float-button/demo/placement.tsx
Normal file
74
components/float-button/demo/placement.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
CommentOutlined,
|
||||
DownOutlined,
|
||||
LeftOutlined,
|
||||
RightOutlined,
|
||||
UpOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import { Flex, FloatButton } from 'antd';
|
||||
|
||||
const BOX_SIZE = 100;
|
||||
const BUTTON_SIZE = 40;
|
||||
|
||||
const wrapperStyle: React.CSSProperties = {
|
||||
width: '100%',
|
||||
height: '100vh',
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
};
|
||||
|
||||
const boxStyle: React.CSSProperties = {
|
||||
width: BOX_SIZE,
|
||||
height: BOX_SIZE,
|
||||
position: 'relative',
|
||||
};
|
||||
|
||||
const insetInlineEnd: React.CSSProperties['insetInlineEnd'][] = [
|
||||
(BOX_SIZE - BUTTON_SIZE) / 2,
|
||||
-(BUTTON_SIZE / 2),
|
||||
(BOX_SIZE - BUTTON_SIZE) / 2,
|
||||
BOX_SIZE - BUTTON_SIZE / 2,
|
||||
];
|
||||
|
||||
const bottom: React.CSSProperties['bottom'][] = [
|
||||
BOX_SIZE - BUTTON_SIZE / 2,
|
||||
(BOX_SIZE - BUTTON_SIZE) / 2,
|
||||
-BUTTON_SIZE / 2,
|
||||
(BOX_SIZE - BUTTON_SIZE) / 2,
|
||||
];
|
||||
|
||||
const icons = [
|
||||
<UpOutlined key="up" />,
|
||||
<RightOutlined key="right" />,
|
||||
<DownOutlined key="down" />,
|
||||
<LeftOutlined key="left" />,
|
||||
];
|
||||
|
||||
const App: React.FC = () => (
|
||||
<Flex justify="space-evenly" align="center" style={wrapperStyle}>
|
||||
<div style={boxStyle}>
|
||||
{(['top', 'right', 'bottom', 'left'] as const).map((placement, i) => {
|
||||
const style: React.CSSProperties = {
|
||||
position: 'absolute',
|
||||
insetInlineEnd: insetInlineEnd[i],
|
||||
bottom: bottom[i],
|
||||
};
|
||||
return (
|
||||
<FloatButton.Group
|
||||
key={placement}
|
||||
trigger="click"
|
||||
placement={placement}
|
||||
style={style}
|
||||
icon={icons[i]}
|
||||
>
|
||||
<FloatButton />
|
||||
<FloatButton icon={<CommentOutlined />} />
|
||||
</FloatButton.Group>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</Flex>
|
||||
);
|
||||
|
||||
export default App;
|
@ -26,6 +26,7 @@ tag: 5.0.0
|
||||
<code src="./demo/group.tsx" iframe="360">FloatButton Group</code>
|
||||
<code src="./demo/group-menu.tsx" iframe="360">Menu mode</code>
|
||||
<code src="./demo/controlled.tsx" iframe="360">Controlled mode</code>
|
||||
<code src="./demo/placement.tsx" iframe="380" version="5.21.0">placement</code>
|
||||
<code src="./demo/back-top.tsx" iframe="360">BackTop</code>
|
||||
<code src="./demo/badge.tsx" iframe="360">badge</code>
|
||||
<code src="./demo/badge-debug.tsx" iframe="360" debug>debug dot</code>
|
||||
@ -59,6 +60,7 @@ Common props ref:[Common props](/docs/react/common-props)
|
||||
| trigger | Which action can trigger menu open/close | `click` \| `hover` | - | |
|
||||
| open | Whether the menu is visible or not, use it with trigger | boolean | - | |
|
||||
| closeIcon | Customize close button icon | React.ReactNode | `<CloseOutlined />` | |
|
||||
| placement | Customize menu animation placement | `top` \| `left` \| `right` \| `bottom` | `top` | 5.21.0 |
|
||||
| onOpenChange | Callback executed when active menu is changed, use it with trigger | (open: boolean) => void | - | |
|
||||
|
||||
### FloatButton.BackTop
|
||||
|
@ -27,6 +27,7 @@ tag: 5.0.0
|
||||
<code src="./demo/group.tsx" iframe="360">浮动按钮组</code>
|
||||
<code src="./demo/group-menu.tsx" iframe="360">菜单模式</code>
|
||||
<code src="./demo/controlled.tsx" iframe="360">受控模式</code>
|
||||
<code src="./demo/placement.tsx" iframe="380" version="5.21.0">弹出方向</code>
|
||||
<code src="./demo/back-top.tsx" iframe="360">回到顶部</code>
|
||||
<code src="./demo/badge.tsx" iframe="360">徽标数</code>
|
||||
<code src="./demo/badge-debug.tsx" iframe="360" debug>调试小圆点使用</code>
|
||||
@ -60,6 +61,7 @@ tag: 5.0.0
|
||||
| trigger | 触发方式(有触发方式为菜单模式) | `click` \| `hover` | - | |
|
||||
| open | 受控展开,需配合 trigger 一起使用 | boolean | - | |
|
||||
| closeIcon | 自定义关闭按钮 | React.ReactNode | `<CloseOutlined />` | |
|
||||
| placement | 自定义菜单弹出位置 | `top` \| `left` \| `right` \| `bottom` | `top` | 5.21.0 |
|
||||
| onOpenChange | 展开收起时的回调,需配合 trigger 一起使用 | (open: boolean) => void | - | |
|
||||
|
||||
### FloatButton.BackTop
|
||||
|
@ -49,6 +49,8 @@ export interface FloatButtonGroupProps extends FloatButtonProps {
|
||||
open?: boolean;
|
||||
// 关闭按钮自定义图标
|
||||
closeIcon?: React.ReactNode;
|
||||
// 菜单弹出方向
|
||||
placement?: 'top' | 'left' | 'right' | 'bottom';
|
||||
// 展开收起的回调
|
||||
onOpenChange?: (open: boolean) => void;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import type { CSSObject } from '@ant-design/cssinjs';
|
||||
import { Keyframes, unit } from '@ant-design/cssinjs';
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { resetComponent } from '../../style';
|
||||
import { initFadeMotion } from '../../style/motion/fade';
|
||||
import { initMotion } from '../../style/motion/motion';
|
||||
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
|
||||
import { genStyleHooks, mergeToken } from '../../theme/internal';
|
||||
import getOffset from '../util';
|
||||
import floatButtonGroupMotion from './keyframes';
|
||||
|
||||
/** Component only token. Which will handle additional calculation of alias token */
|
||||
export interface ComponentToken {
|
||||
@ -26,7 +26,7 @@ export interface ComponentToken {
|
||||
* @desc FloatButton 组件的 Token
|
||||
* @descEN Token for FloatButton component
|
||||
*/
|
||||
type FloatButtonToken = FullToken<'FloatButton'> & {
|
||||
export type FloatButtonToken = FullToken<'FloatButton'> & {
|
||||
/**
|
||||
* @desc FloatButton 颜色
|
||||
* @descEN Color of FloatButton
|
||||
@ -86,58 +86,6 @@ type FloatButtonToken = FullToken<'FloatButton'> & {
|
||||
floatButtonInsetInlineEnd: number;
|
||||
};
|
||||
|
||||
const initFloatButtonGroupMotion = (token: FloatButtonToken) => {
|
||||
const { componentCls, floatButtonSize, motionDurationSlow, motionEaseInOutCirc } = token;
|
||||
const groupPrefixCls = `${componentCls}-group`;
|
||||
const moveDownIn = new Keyframes('antFloatButtonMoveDownIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(0, ${unit(floatButtonSize)}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
|
||||
const moveDownOut = new Keyframes('antFloatButtonMoveDownOut', {
|
||||
'0%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(0, ${unit(floatButtonSize)}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
|
||||
return [
|
||||
{
|
||||
[`${groupPrefixCls}-wrap`]: {
|
||||
...initMotion(`${groupPrefixCls}-wrap`, moveDownIn, moveDownOut, motionDurationSlow, true),
|
||||
},
|
||||
},
|
||||
{
|
||||
[`${groupPrefixCls}-wrap`]: {
|
||||
[`
|
||||
&${groupPrefixCls}-wrap-enter,
|
||||
&${groupPrefixCls}-wrap-appear
|
||||
`]: {
|
||||
opacity: 0,
|
||||
animationTimingFunction: motionEaseInOutCirc,
|
||||
},
|
||||
[`&${groupPrefixCls}-wrap-leave`]: {
|
||||
animationTimingFunction: motionEaseInOutCirc,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
// ============================== Group ==============================
|
||||
const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token) => {
|
||||
const {
|
||||
@ -157,22 +105,25 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
|
||||
[groupPrefixCls]: {
|
||||
...resetComponent(token),
|
||||
zIndex: zIndexPopupBase,
|
||||
display: 'block',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: 'none',
|
||||
position: 'fixed',
|
||||
width: floatButtonSize,
|
||||
height: 'auto',
|
||||
boxShadow: 'none',
|
||||
minWidth: floatButtonSize,
|
||||
minHeight: floatButtonSize,
|
||||
insetInlineEnd: token.floatButtonInsetInlineEnd,
|
||||
insetBlockEnd: token.floatButtonInsetBlockEnd,
|
||||
bottom: token.floatButtonInsetBlockEnd,
|
||||
borderRadius: borderRadiusLG,
|
||||
|
||||
[`${groupPrefixCls}-wrap`]: {
|
||||
zIndex: -1,
|
||||
display: 'block',
|
||||
position: 'relative',
|
||||
marginBottom: margin,
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
position: 'absolute',
|
||||
},
|
||||
[`&${groupPrefixCls}-rtl`]: {
|
||||
direction: 'rtl',
|
||||
@ -181,14 +132,30 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
|
||||
position: 'static',
|
||||
},
|
||||
},
|
||||
[`${groupPrefixCls}-top > ${groupPrefixCls}-wrap`]: {
|
||||
flexDirection: 'column',
|
||||
top: 'auto',
|
||||
bottom: calc(floatButtonSize).add(margin).equal(),
|
||||
},
|
||||
[`${groupPrefixCls}-bottom > ${groupPrefixCls}-wrap`]: {
|
||||
flexDirection: 'column',
|
||||
top: calc(floatButtonSize).add(margin).equal(),
|
||||
bottom: 'auto',
|
||||
},
|
||||
[`${groupPrefixCls}-right > ${groupPrefixCls}-wrap`]: {
|
||||
flexDirection: 'row',
|
||||
left: { _skip_check_: true, value: calc(floatButtonSize).add(margin).equal() },
|
||||
right: { _skip_check_: true, value: 'auto' },
|
||||
},
|
||||
[`${groupPrefixCls}-left > ${groupPrefixCls}-wrap`]: {
|
||||
flexDirection: 'row',
|
||||
left: { _skip_check_: true, value: 'auto' },
|
||||
right: { _skip_check_: true, value: calc(floatButtonSize).add(margin).equal() },
|
||||
},
|
||||
[`${groupPrefixCls}-circle`]: {
|
||||
[`${componentCls}-circle:not(:last-child)`]: {
|
||||
marginBottom: token.margin,
|
||||
[`${componentCls}-body`]: {
|
||||
width: floatButtonSize,
|
||||
height: floatButtonSize,
|
||||
borderRadius: '50%',
|
||||
},
|
||||
gap: margin,
|
||||
[`${groupPrefixCls}-wrap`]: {
|
||||
gap: margin,
|
||||
},
|
||||
},
|
||||
[`${groupPrefixCls}-square`]: {
|
||||
@ -217,14 +184,23 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
|
||||
},
|
||||
},
|
||||
[`${groupPrefixCls}-wrap`]: {
|
||||
display: 'block',
|
||||
borderRadius: borderRadiusLG,
|
||||
boxShadow: token.boxShadowSecondary,
|
||||
[`${componentCls}-square`]: {
|
||||
boxShadow: 'none',
|
||||
marginTop: 0,
|
||||
borderRadius: 0,
|
||||
padding: floatButtonBodyPadding,
|
||||
[`${componentCls}-body`]: {
|
||||
width: token.floatButtonBodySize,
|
||||
height: token.floatButtonBodySize,
|
||||
borderRadius: borderRadiusSM,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
[`${groupPrefixCls}-top > ${groupPrefixCls}-wrap, ${groupPrefixCls}-bottom > ${groupPrefixCls}-wrap`]:
|
||||
{
|
||||
[`> ${componentCls}-square`]: {
|
||||
'&:first-child': {
|
||||
borderStartStartRadius: borderRadiusLG,
|
||||
borderStartEndRadius: borderRadiusLG,
|
||||
@ -236,13 +212,25 @@ const floatButtonGroupStyle: GenerateStyle<FloatButtonToken, CSSObject> = (token
|
||||
'&:not(:last-child)': {
|
||||
borderBottom: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
|
||||
},
|
||||
[`${componentCls}-body`]: {
|
||||
width: token.floatButtonBodySize,
|
||||
height: token.floatButtonBodySize,
|
||||
},
|
||||
},
|
||||
[`${groupPrefixCls}-left > ${groupPrefixCls}-wrap, ${groupPrefixCls}-right > ${groupPrefixCls}-wrap`]:
|
||||
{
|
||||
[`> ${componentCls}-square`]: {
|
||||
'&:first-child': {
|
||||
borderStartStartRadius: borderRadiusLG,
|
||||
borderEndStartRadius: borderRadiusLG,
|
||||
},
|
||||
'&:last-child': {
|
||||
borderStartEndRadius: borderRadiusLG,
|
||||
borderEndEndRadius: borderRadiusLG,
|
||||
},
|
||||
'&:not(:last-child)': {
|
||||
borderInlineEnd: `${unit(token.lineWidth)} ${token.lineType} ${token.colorSplit}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${groupPrefixCls}-circle-shadow`]: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
@ -290,7 +278,7 @@ const sharedFloatButtonStyle: GenerateStyle<FloatButtonToken, CSSObject> = (toke
|
||||
width: floatButtonSize,
|
||||
height: floatButtonSize,
|
||||
insetInlineEnd: token.floatButtonInsetInlineEnd,
|
||||
insetBlockEnd: token.floatButtonInsetBlockEnd,
|
||||
bottom: token.floatButtonInsetBlockEnd,
|
||||
boxShadow: token.boxShadowSecondary,
|
||||
// Pure Panel
|
||||
'&-pure': {
|
||||
@ -454,12 +442,11 @@ export default genStyleHooks(
|
||||
floatButtonBodyPadding: paddingXXS,
|
||||
badgeOffset: calc(paddingXXS).mul(1.5).equal(),
|
||||
});
|
||||
|
||||
return [
|
||||
floatButtonGroupStyle(floatButtonToken),
|
||||
sharedFloatButtonStyle(floatButtonToken),
|
||||
initFadeMotion(token),
|
||||
initFloatButtonGroupMotion(floatButtonToken),
|
||||
floatButtonGroupMotion(floatButtonToken),
|
||||
];
|
||||
},
|
||||
prepareComponentToken,
|
||||
|
153
components/float-button/style/keyframes.ts
Normal file
153
components/float-button/style/keyframes.ts
Normal file
@ -0,0 +1,153 @@
|
||||
import { Keyframes, unit } from '@ant-design/cssinjs';
|
||||
|
||||
import type { FloatButtonToken } from '.';
|
||||
import { initMotion } from '../../style/motion/motion';
|
||||
|
||||
const floatButtonGroupMotion = (token: FloatButtonToken) => {
|
||||
const { componentCls, floatButtonSize, motionDurationSlow, motionEaseInOutCirc, calc } = token;
|
||||
const moveTopIn = new Keyframes('antFloatButtonMoveTopIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(0, ${unit(floatButtonSize)}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
const moveTopOut = new Keyframes('antFloatButtonMoveTopOut', {
|
||||
'0%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(0, ${unit(floatButtonSize)}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
const moveRightIn = new Keyframes('antFloatButtonMoveRightIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(${calc(floatButtonSize).mul(-1).equal()}, 0, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
const moveRightOut = new Keyframes('antFloatButtonMoveRightOut', {
|
||||
'0%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(${calc(floatButtonSize).mul(-1).equal()}, 0, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
const moveBottomIn = new Keyframes('antFloatButtonMoveBottomIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(0, ${calc(floatButtonSize).mul(-1).equal()}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
const moveBottomOut = new Keyframes('antFloatButtonMoveBottomOut', {
|
||||
'0%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(0, ${calc(floatButtonSize).mul(-1).equal()}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
const moveLeftIn = new Keyframes('antFloatButtonMoveLeftIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(${unit(floatButtonSize)}, 0, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
'100%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
});
|
||||
const moveLeftOut = new Keyframes('antFloatButtonMoveLeftOut', {
|
||||
'0%': {
|
||||
transform: 'translate3d(0, 0, 0)',
|
||||
transformOrigin: '0 0',
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(${unit(floatButtonSize)}, 0, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
const groupPrefixCls = `${componentCls}-group`;
|
||||
return [
|
||||
{
|
||||
[groupPrefixCls]: {
|
||||
[`&${groupPrefixCls}-top ${groupPrefixCls}-wrap`]: initMotion(
|
||||
`${groupPrefixCls}-wrap`,
|
||||
moveTopIn,
|
||||
moveTopOut,
|
||||
motionDurationSlow,
|
||||
true,
|
||||
),
|
||||
[`&${groupPrefixCls}-bottom ${groupPrefixCls}-wrap`]: initMotion(
|
||||
`${groupPrefixCls}-wrap`,
|
||||
moveBottomIn,
|
||||
moveBottomOut,
|
||||
motionDurationSlow,
|
||||
true,
|
||||
),
|
||||
[`&${groupPrefixCls}-left ${groupPrefixCls}-wrap`]: initMotion(
|
||||
`${groupPrefixCls}-wrap`,
|
||||
moveLeftIn,
|
||||
moveLeftOut,
|
||||
motionDurationSlow,
|
||||
true,
|
||||
),
|
||||
[`&${groupPrefixCls}-right ${groupPrefixCls}-wrap`]: initMotion(
|
||||
`${groupPrefixCls}-wrap`,
|
||||
moveRightIn,
|
||||
moveRightOut,
|
||||
motionDurationSlow,
|
||||
true,
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
[`${groupPrefixCls}-wrap`]: {
|
||||
[`&${groupPrefixCls}-wrap-enter, &${groupPrefixCls}-wrap-appear`]: {
|
||||
opacity: 0,
|
||||
animationTimingFunction: motionEaseInOutCirc,
|
||||
},
|
||||
[`&${groupPrefixCls}-wrap-leave`]: {
|
||||
opacity: 1,
|
||||
animationTimingFunction: motionEaseInOutCirc,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export default floatButtonGroupMotion;
|
@ -30400,6 +30400,89 @@ exports[`renders components/form/demo/variant.tsx extend context correctly 1`] =
|
||||
class="ant-form ant-form-horizontal"
|
||||
style="max-width: 600px;"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-row ant-form-item-row"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-6"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
for="variant"
|
||||
title="Form variant"
|
||||
>
|
||||
Form variant
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-form-item-control ant-col-xs-24 ant-col-sm-14"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-segmented"
|
||||
id="variant"
|
||||
>
|
||||
<div
|
||||
class="ant-segmented-group"
|
||||
>
|
||||
<label
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
class="ant-segmented-item-input"
|
||||
type="radio"
|
||||
/>
|
||||
<div
|
||||
class="ant-segmented-item-label"
|
||||
title="outlined"
|
||||
>
|
||||
outlined
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
class="ant-segmented-item ant-segmented-item-selected"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-segmented-item-input"
|
||||
type="radio"
|
||||
/>
|
||||
<div
|
||||
class="ant-segmented-item-label"
|
||||
title="filled"
|
||||
>
|
||||
filled
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
class="ant-segmented-item-input"
|
||||
type="radio"
|
||||
/>
|
||||
<div
|
||||
class="ant-segmented-item-label"
|
||||
title="borderless"
|
||||
>
|
||||
borderless
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-form-item"
|
||||
>
|
||||
|
@ -12619,6 +12619,89 @@ exports[`renders components/form/demo/variant.tsx correctly 1`] = `
|
||||
class="ant-form ant-form-horizontal"
|
||||
style="max-width:600px"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item"
|
||||
>
|
||||
<div
|
||||
class="ant-row ant-form-item-row"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-form-item-label ant-col-xs-24 ant-col-sm-6"
|
||||
>
|
||||
<label
|
||||
class=""
|
||||
for="variant"
|
||||
title="Form variant"
|
||||
>
|
||||
Form variant
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-form-item-control ant-col-xs-24 ant-col-sm-14"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input"
|
||||
>
|
||||
<div
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<div
|
||||
class="ant-segmented"
|
||||
id="variant"
|
||||
>
|
||||
<div
|
||||
class="ant-segmented-group"
|
||||
>
|
||||
<label
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
class="ant-segmented-item-input"
|
||||
type="radio"
|
||||
/>
|
||||
<div
|
||||
class="ant-segmented-item-label"
|
||||
title="outlined"
|
||||
>
|
||||
outlined
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
class="ant-segmented-item ant-segmented-item-selected"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="ant-segmented-item-input"
|
||||
type="radio"
|
||||
/>
|
||||
<div
|
||||
class="ant-segmented-item-label"
|
||||
title="filled"
|
||||
>
|
||||
filled
|
||||
</div>
|
||||
</label>
|
||||
<label
|
||||
class="ant-segmented-item"
|
||||
>
|
||||
<input
|
||||
class="ant-segmented-item-input"
|
||||
type="radio"
|
||||
/>
|
||||
<div
|
||||
class="ant-segmented-item-label"
|
||||
title="borderless"
|
||||
>
|
||||
borderless
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-form-item"
|
||||
>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Cascader,
|
||||
@ -9,7 +9,9 @@ import {
|
||||
Mentions,
|
||||
Select,
|
||||
TreeSelect,
|
||||
Segmented,
|
||||
} from 'antd';
|
||||
import type { FormProps } from 'antd';
|
||||
|
||||
const { RangePicker } = DatePicker;
|
||||
|
||||
@ -24,78 +26,99 @@ const formItemLayout = {
|
||||
},
|
||||
};
|
||||
|
||||
const App: React.FC = () => (
|
||||
<Form {...formItemLayout} variant="filled" style={{ maxWidth: 600 }}>
|
||||
<Form.Item label="Input" name="Input" rules={[{ required: true, message: 'Please input!' }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
const App: React.FC = () => {
|
||||
const [componentVariant, setComponentVariant] = useState<FormProps['variant']>('filled');
|
||||
|
||||
<Form.Item
|
||||
label="InputNumber"
|
||||
name="InputNumber"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
const onFormVariantChange = ({ variant }: { variant: FormProps['variant'] }) => {
|
||||
setComponentVariant(variant);
|
||||
};
|
||||
return (
|
||||
<Form
|
||||
{...formItemLayout}
|
||||
onValuesChange={onFormVariantChange}
|
||||
variant={componentVariant}
|
||||
style={{ maxWidth: 600 }}
|
||||
initialValues={{ variant: componentVariant }}
|
||||
>
|
||||
<InputNumber style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Form variant" name="variant">
|
||||
<Segmented options={['outlined', 'filled', 'borderless']} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="TextArea"
|
||||
name="TextArea"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Input.TextArea />
|
||||
</Form.Item>
|
||||
<Form.Item label="Input" name="Input" rules={[{ required: true, message: 'Please input!' }]}>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Mentions"
|
||||
name="Mentions"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Mentions />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="InputNumber"
|
||||
name="InputNumber"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<InputNumber style={{ width: '100%' }} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Select" name="Select" rules={[{ required: true, message: 'Please input!' }]}>
|
||||
<Select />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="TextArea"
|
||||
name="TextArea"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Input.TextArea />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="Cascader"
|
||||
name="Cascader"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Cascader />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Mentions"
|
||||
name="Mentions"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Mentions />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="TreeSelect"
|
||||
name="TreeSelect"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<TreeSelect />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Select"
|
||||
name="Select"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Select />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="DatePicker"
|
||||
name="DatePicker"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<DatePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Cascader"
|
||||
name="Cascader"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<Cascader />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="RangePicker"
|
||||
name="RangePicker"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<RangePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="TreeSelect"
|
||||
name="TreeSelect"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<TreeSelect />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item wrapperCol={{ offset: 6, span: 16 }}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
<Form.Item
|
||||
label="DatePicker"
|
||||
name="DatePicker"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<DatePicker />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label="RangePicker"
|
||||
name="RangePicker"
|
||||
rules={[{ required: true, message: 'Please input!' }]}
|
||||
>
|
||||
<RangePicker />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item wrapperCol={{ offset: 6, span: 16 }}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
Submit
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
@ -38,7 +38,7 @@ export interface ComponentToken {
|
||||
*/
|
||||
cardPaddingLG: string;
|
||||
/**
|
||||
* @desc 标齐页标题文本大小
|
||||
* @desc 标签页标题文本大小
|
||||
* @descEN Font size of title
|
||||
*/
|
||||
titleFontSize: number;
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "antd",
|
||||
"version": "5.20.1",
|
||||
"version": "5.20.2",
|
||||
"description": "An enterprise-class UI design language and React components implementation",
|
||||
"keywords": [
|
||||
"ant",
|
||||
|
Loading…
Reference in New Issue
Block a user