This commit is contained in:
2026-05-25 17:08:18 +08:00
parent df501f6151
commit f1259b71b5
9178 changed files with 1626125 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
import * as React from 'react';
export interface IndicatorProps {
prefixCls: string;
percent?: number;
className?: string;
style?: React.CSSProperties;
}
export default function Looper(props: IndicatorProps): React.JSX.Element;
+36
View File
@@ -0,0 +1,36 @@
"use strict";
"use client";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = Looper;
var React = _interopRequireWildcard(require("react"));
var _clsx = require("clsx");
var _Progress = _interopRequireDefault(require("./Progress"));
function Looper(props) {
const {
prefixCls,
percent = 0,
className,
style
} = props;
const dotClassName = `${prefixCls}-dot`;
const holderClassName = `${dotClassName}-holder`;
const hideClassName = `${holderClassName}-hidden`;
// ===================== Render =====================
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
className: (0, _clsx.clsx)(holderClassName, className, percent > 0 && hideClassName),
style: style
}, /*#__PURE__*/React.createElement("span", {
className: (0, _clsx.clsx)(dotClassName, `${prefixCls}-dot-spin`)
}, [1, 2, 3, 4].map(i => (/*#__PURE__*/React.createElement("i", {
className: `${prefixCls}-dot-item`,
key: i
}))))), /*#__PURE__*/React.createElement(_Progress.default, {
prefixCls: prefixCls,
percent: percent
}));
}
+7
View File
@@ -0,0 +1,7 @@
import * as React from 'react';
export interface ProgressProps {
prefixCls: string;
percent: number;
}
declare const Progress: React.FC<Readonly<ProgressProps>>;
export default Progress;
+77
View File
@@ -0,0 +1,77 @@
"use strict";
"use client";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var React = _interopRequireWildcard(require("react"));
var _useLayoutEffect = _interopRequireDefault(require("@rc-component/util/lib/hooks/useLayoutEffect"));
var _clsx = require("clsx");
const viewSize = 100;
const borderWidth = viewSize / 5;
const radius = viewSize / 2 - borderWidth / 2;
const circumference = radius * 2 * Math.PI;
const position = 50;
const CustomCircle = props => {
const {
dotClassName,
style,
hasCircleCls
} = props;
return /*#__PURE__*/React.createElement("circle", {
className: (0, _clsx.clsx)(`${dotClassName}-circle`, {
[`${dotClassName}-circle-bg`]: hasCircleCls
}),
r: radius,
cx: position,
cy: position,
strokeWidth: borderWidth,
style: style
});
};
const Progress = ({
percent,
prefixCls
}) => {
const dotClassName = `${prefixCls}-dot`;
const holderClassName = `${dotClassName}-holder`;
const hideClassName = `${holderClassName}-hidden`;
const [render, setRender] = React.useState(false);
// ==================== Visible =====================
(0, _useLayoutEffect.default)(() => {
if (percent !== 0) {
setRender(true);
}
}, [percent !== 0]);
// ==================== Progress ====================
const safePtg = Math.max(Math.min(percent, 100), 0);
// ===================== Render =====================
if (!render) {
return null;
}
const circleStyle = {
strokeDashoffset: `${circumference / 4}`,
strokeDasharray: `${circumference * safePtg / 100} ${circumference * (100 - safePtg) / 100}`
};
return /*#__PURE__*/React.createElement("span", {
className: (0, _clsx.clsx)(holderClassName, `${dotClassName}-progress`, {
[hideClassName]: safePtg <= 0
})
}, /*#__PURE__*/React.createElement("svg", {
viewBox: `0 0 ${viewSize} ${viewSize}`,
role: "progressbar",
"aria-valuemin": 0,
"aria-valuemax": 100,
"aria-valuenow": safePtg
}, /*#__PURE__*/React.createElement(CustomCircle, {
dotClassName: dotClassName,
hasCircleCls: true
}), /*#__PURE__*/React.createElement(CustomCircle, {
dotClassName: dotClassName,
style: circleStyle
})));
};
var _default = exports.default = Progress;
+9
View File
@@ -0,0 +1,9 @@
import * as React from 'react';
export interface IndicatorProps {
prefixCls: string;
indicator?: React.ReactNode;
percent?: number;
className?: string;
style?: React.CSSProperties;
}
export default function Indicator(props: IndicatorProps): React.JSX.Element;
+39
View File
@@ -0,0 +1,39 @@
"use strict";
"use client";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = Indicator;
var React = _interopRequireWildcard(require("react"));
var _clsx = require("clsx");
var _reactNode = require("../../_util/reactNode");
var _Looper = _interopRequireDefault(require("./Looper"));
function Indicator(props) {
const {
prefixCls,
indicator,
percent,
className,
style
} = props;
const dotClassName = `${prefixCls}-dot`;
if (indicator && /*#__PURE__*/React.isValidElement(indicator)) {
return (0, _reactNode.cloneElement)(indicator, currentProps => ({
className: (0, _clsx.clsx)(currentProps.className, dotClassName, className),
style: {
...currentProps.style,
...style
},
percent
}));
}
return /*#__PURE__*/React.createElement(_Looper.default, {
prefixCls: prefixCls,
percent: percent,
className: className,
style: style
});
}
+63
View File
@@ -0,0 +1,63 @@
import * as React from 'react';
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks';
import type { SizeType } from '../config-provider/SizeContext';
export type SpinIndicator = React.ReactElement<HTMLElement>;
export type SpinSemanticName = keyof SpinSemanticClassNames & keyof SpinSemanticStyles;
export type SpinSemanticClassNames = {
root?: string;
section?: string;
indicator?: string;
description?: string;
container?: string;
/** @deprecated Please use `description` instead */
tip?: string;
/** @deprecated Please use `root` instead */
mask?: string;
};
export type SpinSemanticStyles = {
root?: React.CSSProperties;
section?: React.CSSProperties;
indicator?: React.CSSProperties;
description?: React.CSSProperties;
container?: React.CSSProperties;
/** @deprecated Please use `description` instead */
tip?: React.CSSProperties;
/** @deprecated Please use `root` instead */
mask?: React.CSSProperties;
};
export type SpinClassNamesType = SemanticClassNamesType<SpinProps, SpinSemanticClassNames>;
export type SpinStylesType = SemanticStylesType<SpinProps, SpinSemanticStyles>;
export interface SpinProps {
prefixCls?: string;
className?: string;
rootClassName?: string;
/** Whether Spin is spinning */
spinning?: boolean;
style?: React.CSSProperties;
/**
* Note: `default` is deprecated and will be removed in v7, please use `medium` instead.
*/
size?: SizeType | 'default';
/** Customize description content when Spin has children */
/** @deprecated Please use `description` instead */
tip?: React.ReactNode;
description?: React.ReactNode;
/** Specifies a delay in milliseconds for loading state (prevent flush) */
delay?: number;
/** The className of wrapper when Spin has children */
/** @deprecated Please use `classNames.root` instead */
wrapperClassName?: string;
/** React node of the spinning indicator */
indicator?: SpinIndicator;
children?: React.ReactNode;
/** Display a backdrop with the `Spin` component */
fullscreen?: boolean;
percent?: number | 'auto';
classNames?: SpinClassNamesType;
styles?: SpinStylesType;
}
export type SpinType = React.FC<SpinProps> & {
setDefaultIndicator: (indicator: React.ReactNode) => void;
};
declare const Spin: SpinType;
export default Spin;
+151
View File
@@ -0,0 +1,151 @@
"use strict";
"use client";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var React = _interopRequireWildcard(require("react"));
var _clsx = require("clsx");
var _throttleDebounce = require("throttle-debounce");
var _hooks = require("../_util/hooks");
var _warning = require("../_util/warning");
var _context = require("../config-provider/context");
var _useSize = _interopRequireDefault(require("../config-provider/hooks/useSize"));
var _Indicator = _interopRequireDefault(require("./Indicator"));
var _index = _interopRequireDefault(require("./style/index"));
var _usePercent = _interopRequireDefault(require("./usePercent"));
// Render indicator
let defaultIndicator;
function shouldDelay(spinning, delay) {
return !!spinning && !!delay && !Number.isNaN(Number(delay));
}
const Spin = props => {
const {
prefixCls: customizePrefixCls,
spinning: customSpinning = true,
delay = 0,
className,
rootClassName,
size,
tip,
description,
wrapperClassName,
style,
children,
fullscreen = false,
indicator,
percent,
classNames,
styles,
...restProps
} = props;
const {
getPrefixCls,
direction,
indicator: contextIndicator,
className: contextClassName,
style: contextStyle,
classNames: contextClassNames,
styles: contextStyles
} = (0, _context.useComponentConfig)('spin');
const prefixCls = getPrefixCls('spin', customizePrefixCls);
const [hashId, cssVarCls] = (0, _index.default)(prefixCls);
const [spinning, setSpinning] = React.useState(() => customSpinning && !shouldDelay(customSpinning, delay));
const mergedPercent = (0, _usePercent.default)(spinning, percent);
React.useEffect(() => {
if (customSpinning) {
const showSpinning = (0, _throttleDebounce.debounce)(delay, () => {
setSpinning(true);
});
showSpinning();
return () => {
showSpinning?.cancel?.();
};
}
setSpinning(false);
}, [delay, customSpinning]);
// ======================= Size ======================
const mergedSize = (0, _useSize.default)(ctx => size ?? ctx);
if (process.env.NODE_ENV !== 'production') {
const warning = (0, _warning.devUseWarning)('Spin');
warning.deprecated(size !== 'default', 'size="default"', 'size="medium"');
}
// ======================= Description ======================
const mergedDescription = description ?? tip;
// =============== Merged Props for Semantic ================
const mergedProps = {
...props,
size: mergedSize,
spinning,
tip: mergedDescription,
description: mergedDescription,
fullscreen,
children,
percent: mergedPercent
};
// ========================= Style ==========================
const [mergedClassNames, mergedStyles] = (0, _hooks.useMergeSemantic)([contextClassNames, classNames], [contextStyles, styles], {
props: mergedProps
});
// ======================== Warning =========================
if (process.env.NODE_ENV !== 'production') {
const warning = (0, _warning.devUseWarning)('Spin');
warning.deprecated(!tip, 'tip', 'description');
warning.deprecated(!wrapperClassName, 'wrapperClassName', 'classNames.root');
warning.deprecated(!(mergedClassNames?.tip || mergedStyles?.tip), 'classNames.tip and styles.tip', 'classNames.description and styles.description');
warning.deprecated(!(mergedClassNames?.mask || mergedStyles?.mask), 'classNames.mask and styles.mask', 'classNames.root and styles.root');
}
// ======================= Indicator ========================
const mergedIndicator = indicator ?? contextIndicator ?? defaultIndicator;
// ========================= Render =========================
const hasChildren = typeof children !== 'undefined';
const isNested = hasChildren || fullscreen;
const indicatorNode = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(_Indicator.default, {
className: (0, _clsx.clsx)(mergedClassNames.indicator),
style: mergedStyles.indicator,
prefixCls: prefixCls,
indicator: mergedIndicator,
percent: mergedPercent
}), mergedDescription && (/*#__PURE__*/React.createElement("div", {
className: (0, _clsx.clsx)(`${prefixCls}-description`, mergedClassNames.tip, mergedClassNames.description),
style: {
...mergedStyles.tip,
...mergedStyles.description
}
}, mergedDescription)));
return /*#__PURE__*/React.createElement("div", {
className: (0, _clsx.clsx)(prefixCls, {
[`${prefixCls}-sm`]: mergedSize === 'small',
[`${prefixCls}-lg`]: mergedSize === 'large',
[`${prefixCls}-spinning`]: spinning,
[`${prefixCls}-rtl`]: direction === 'rtl',
[`${prefixCls}-fullscreen`]: fullscreen
}, rootClassName, mergedClassNames.root, fullscreen && mergedClassNames.mask, isNested ? wrapperClassName : [`${prefixCls}-section`, mergedClassNames.section], contextClassName, className, hashId, cssVarCls),
style: {
...mergedStyles.root,
...(!isNested ? mergedStyles.section : {}),
...(fullscreen ? mergedStyles.mask : {}),
...contextStyle,
...style
},
"aria-live": "polite",
"aria-busy": spinning,
...restProps
}, spinning && (isNested ? (/*#__PURE__*/React.createElement("div", {
className: (0, _clsx.clsx)(`${prefixCls}-section`, mergedClassNames.section),
style: mergedStyles.section
}, indicatorNode)) : indicatorNode), hasChildren && (/*#__PURE__*/React.createElement("div", {
className: (0, _clsx.clsx)(`${prefixCls}-container`, mergedClassNames.container),
style: mergedStyles.container
}, children)));
};
Spin.setDefaultIndicator = indicator => {
defaultIndicator = indicator;
};
if (process.env.NODE_ENV !== 'production') {
Spin.displayName = 'Spin';
}
var _default = exports.default = Spin;
+26
View File
@@ -0,0 +1,26 @@
import type { GetDefaultToken } from '../../theme/internal';
export interface ComponentToken {
/**
* @desc 内容区域高度
* @descEN Height of content area
*/
contentHeight: number | string;
/**
* @desc 加载图标尺寸
* @descEN Loading icon size
*/
dotSize: number;
/**
* @desc 小号加载图标尺寸
* @descEN Small loading icon size
*/
dotSizeSM: number;
/**
* @desc 大号加载图标尺寸
* @descEN Large loading icon size
*/
dotSizeLG: number;
}
export declare const prepareComponentToken: GetDefaultToken<'Spin'>;
declare const _default: (prefixCls: string, rootCls?: string) => readonly [string, string];
export default _default;
+252
View File
@@ -0,0 +1,252 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.prepareComponentToken = exports.default = void 0;
var _cssinjs = require("@ant-design/cssinjs");
var _style = require("../../style");
var _internal = require("../../theme/internal");
var _genStyleUtils = require("../../theme/util/genStyleUtils");
const antSpinMove = new _cssinjs.Keyframes('antSpinMove', {
to: {
opacity: 1
}
});
const antRotate = new _cssinjs.Keyframes('antRotate', {
to: {
transform: 'rotate(405deg)'
}
});
// =============================== Spin ===============================
const genSpinStyle = token => {
const {
componentCls
} = token;
const sectionCls = `${componentCls}-section`;
return {
[componentCls]: {
...(0, _style.resetComponent)(token),
position: 'relative',
'&-rtl': {
direction: 'rtl'
},
// ========================== Section ===========================
[`&${sectionCls}, ${sectionCls}`]: {
display: 'flex',
alignItems: 'center',
flexDirection: 'column',
gap: token.paddingSM,
color: token.colorPrimary
},
[`&${sectionCls}`]: {
display: 'inline-flex'
},
[sectionCls]: {
position: 'absolute',
top: '50%',
left: {
_skip_check_: true,
value: '50%'
},
transform: 'translate(-50%, -50%)',
zIndex: 1
},
[`${componentCls}-description`]: {
fontSize: token.fontSize,
lineHeight: 1
},
// ========================= Container ==========================
[`${componentCls}-container`]: {
position: 'relative',
transition: `opacity ${token.motionDurationSlow}`,
'&::after': {
position: 'absolute',
top: 0,
insetInlineEnd: 0,
bottom: 0,
insetInlineStart: 0,
zIndex: 10,
width: '100%',
height: '100%',
background: token.colorBgContainer,
opacity: 0,
transition: `all ${token.motionDurationSlow}`,
content: '""',
pointerEvents: 'none'
}
},
// ========================== Spinning ==========================
'&-spinning': {
[`${componentCls}-description`]: {
textShadow: `0 0px 5px ${token.colorBgContainer}`
},
[`${componentCls}-container`]: {
clear: 'both',
opacity: 0.5,
userSelect: 'none',
pointerEvents: 'none',
'&::after': {
opacity: 0.4,
pointerEvents: 'auto'
}
}
},
// ========================= Fullscreen =========================
'&-fullscreen': {
position: 'fixed',
inset: 0,
backgroundColor: token.colorBgMask,
zIndex: token.zIndexPopupBase,
opacity: 0,
pointerEvents: 'none',
transition: `all ${token.motionDurationMid}`,
[`&${componentCls}-spinning`]: {
opacity: 1,
pointerEvents: 'auto'
},
[sectionCls]: {
color: token.colorWhite,
[`${componentCls}-description`]: {
color: token.colorTextLightSolid
}
}
}
}
};
};
// ============================ Indicator =============================
const genIndicatorStyle = token => {
const {
componentCls,
antCls,
motionDurationSlow
} = token;
const [varName, varRef] = (0, _genStyleUtils.genCssVar)(antCls, 'spin');
return {
[componentCls]: {
[varName('dot-holder-size')]: token.dotSize,
[varName('dot-item-size')]: `calc((${varRef('dot-holder-size')} - ${token.marginXXS} / 2) / 2)`,
[`${componentCls}-dot`]: {
// >>> holder
'&-holder': {
width: '1em',
height: '1em',
fontSize: varRef('dot-holder-size'),
display: 'inline-block',
transition: ['transform', 'opacity'].map(prop => `${prop} ${motionDurationSlow} ease`).join(', '),
transformOrigin: '50% 50%',
lineHeight: 1,
'&-hidden': {
transform: 'scale(0.3)',
opacity: 0
}
},
// >>> holder > dot
position: 'relative',
display: 'inline-block',
fontSize: varRef('dot-holder-size'),
width: '1em',
height: '1em',
'&-spin': {
transform: 'rotate(45deg)',
animationName: antRotate,
animationDuration: '1.2s',
animationIterationCount: 'infinite',
animationTimingFunction: 'linear'
},
// >>> holder > dot > item
'&-item': {
position: 'absolute',
display: 'block',
width: varRef('dot-item-size'),
height: varRef('dot-item-size'),
background: 'currentColor',
borderRadius: '100%',
transform: 'scale(0.75)',
transformOrigin: '50% 50%',
opacity: 0.3,
animationName: antSpinMove,
animationDuration: '1s',
animationIterationCount: 'infinite',
animationTimingFunction: 'linear',
animationDirection: 'alternate',
'&:nth-child(1)': {
top: 0,
insetInlineStart: 0,
animationDelay: '0s'
},
'&:nth-child(2)': {
top: 0,
insetInlineEnd: 0,
animationDelay: '0.4s'
},
'&:nth-child(3)': {
insetInlineEnd: 0,
bottom: 0,
animationDelay: '0.8s'
},
'&:nth-child(4)': {
bottom: 0,
insetInlineStart: 0,
animationDelay: '1.2s'
}
},
// ========================= Progress =========================
'&-progress': {
position: 'absolute',
left: '50%',
top: 0,
transform: 'translateX(-50%)'
},
'&-circle': {
strokeLinecap: 'round',
transition: ['stroke-dashoffset', 'stroke-dasharray', 'stroke', 'stroke-width', 'opacity'].map(item => `${item} ${motionDurationSlow} ease`).join(','),
fillOpacity: 0,
stroke: 'currentcolor'
},
'&-circle-bg': {
stroke: token.colorFillSecondary
}
}
}
};
};
// =============================== Size ===============================
const genSizeStyle = token => {
const {
componentCls
} = token;
const [varName] = (0, _genStyleUtils.genCssVar)(token.antCls, 'spin');
return {
[componentCls]: {
'&-sm': {
[varName('dot-holder-size')]: token.dotSizeSM
},
'&-lg': {
[varName('dot-holder-size')]: token.dotSizeLG
}
}
};
};
// ========================= Component Token ==========================
const prepareComponentToken = token => {
const {
controlHeightLG,
controlHeight
} = token;
return {
contentHeight: 400,
dotSize: controlHeightLG / 2,
dotSizeSM: controlHeightLG * 0.35,
dotSizeLG: controlHeight
};
};
// ============================== Export ==============================
exports.prepareComponentToken = prepareComponentToken;
var _default = exports.default = (0, _internal.genStyleHooks)('Spin', token => {
const spinToken = (0, _internal.mergeToken)(token, {
spinDotDefault: token.colorTextDescription
});
return [genSpinStyle(spinToken), genIndicatorStyle(spinToken), genSizeStyle(spinToken)];
}, prepareComponentToken);
+1
View File
@@ -0,0 +1 @@
export default function usePercent(spinning: boolean, percent?: number | 'auto'): number | undefined;
+39
View File
@@ -0,0 +1,39 @@
"use strict";
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = usePercent;
var React = _interopRequireWildcard(require("react"));
const AUTO_INTERVAL = 200;
const STEP_BUCKETS = [[30, 0.05], [70, 0.03], [96, 0.01]];
function usePercent(spinning, percent) {
const [mockPercent, setMockPercent] = React.useState(0);
const mockIntervalRef = React.useRef(null);
const isAuto = percent === 'auto';
React.useEffect(() => {
if (isAuto && spinning) {
setMockPercent(0);
mockIntervalRef.current = setInterval(() => {
setMockPercent(prev => {
const restPTG = 100 - prev;
for (let i = 0; i < STEP_BUCKETS.length; i += 1) {
const [limit, stepPtg] = STEP_BUCKETS[i];
if (prev <= limit) {
return prev + restPTG * stepPtg;
}
}
return prev;
});
}, AUTO_INTERVAL);
}
return () => {
if (mockIntervalRef.current) {
clearInterval(mockIntervalRef.current);
mockIntervalRef.current = null;
}
};
}, [isAuto, spinning]);
return isAuto ? mockPercent : percent;
}