UNPKG

8.89 kBJavaScriptView Raw
1"use client";
2
3var __rest = this && this.__rest || function (s, e) {
4 var t = {};
5 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
6 if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7 if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
8 }
9 return t;
10};
11import * as React from 'react';
12import { useMemo, useRef } from 'react';
13import classnames from 'classnames';
14import CSSMotion from 'rc-motion';
15import { isPresetColor } from '../_util/colors';
16import { cloneElement } from '../_util/reactNode';
17import { ConfigContext } from '../config-provider';
18import Ribbon from './Ribbon';
19import ScrollNumber from './ScrollNumber';
20import useStyle from './style';
21const InternalBadge = (props, ref) => {
22 var _a, _b, _c, _d, _e;
23 const {
24 prefixCls: customizePrefixCls,
25 scrollNumberPrefixCls: customizeScrollNumberPrefixCls,
26 children,
27 status,
28 text,
29 color,
30 count = null,
31 overflowCount = 99,
32 dot = false,
33 size = 'default',
34 title,
35 offset,
36 style,
37 className,
38 rootClassName,
39 classNames,
40 styles,
41 showZero = false
42 } = props,
43 restProps = __rest(props, ["prefixCls", "scrollNumberPrefixCls", "children", "status", "text", "color", "count", "overflowCount", "dot", "size", "title", "offset", "style", "className", "rootClassName", "classNames", "styles", "showZero"]);
44 const {
45 getPrefixCls,
46 direction,
47 badge
48 } = React.useContext(ConfigContext);
49 const prefixCls = getPrefixCls('badge', customizePrefixCls);
50 const [wrapCSSVar, hashId, cssVarCls] = useStyle(prefixCls);
51 // ================================ Misc ================================
52 const numberedDisplayCount = count > overflowCount ? `${overflowCount}+` : count;
53 const isZero = numberedDisplayCount === '0' || numberedDisplayCount === 0;
54 const ignoreCount = count === null || isZero && !showZero;
55 const hasStatus = (status !== null && status !== undefined || color !== null && color !== undefined) && ignoreCount;
56 const showAsDot = dot && !isZero;
57 const mergedCount = showAsDot ? '' : numberedDisplayCount;
58 const isHidden = useMemo(() => {
59 const isEmpty = mergedCount === null || mergedCount === undefined || mergedCount === '';
60 return (isEmpty || isZero && !showZero) && !showAsDot;
61 }, [mergedCount, isZero, showZero, showAsDot]);
62 // Count should be cache in case hidden change it
63 const countRef = useRef(count);
64 if (!isHidden) {
65 countRef.current = count;
66 }
67 const livingCount = countRef.current;
68 // We need cache count since remove motion should not change count display
69 const displayCountRef = useRef(mergedCount);
70 if (!isHidden) {
71 displayCountRef.current = mergedCount;
72 }
73 const displayCount = displayCountRef.current;
74 // We will cache the dot status to avoid shaking on leaved motion
75 const isDotRef = useRef(showAsDot);
76 if (!isHidden) {
77 isDotRef.current = showAsDot;
78 }
79 // =============================== Styles ===============================
80 const mergedStyle = useMemo(() => {
81 if (!offset) {
82 return Object.assign(Object.assign({}, badge === null || badge === void 0 ? void 0 : badge.style), style);
83 }
84 const offsetStyle = {
85 marginTop: offset[1]
86 };
87 if (direction === 'rtl') {
88 offsetStyle.left = parseInt(offset[0], 10);
89 } else {
90 offsetStyle.right = -parseInt(offset[0], 10);
91 }
92 return Object.assign(Object.assign(Object.assign({}, offsetStyle), badge === null || badge === void 0 ? void 0 : badge.style), style);
93 }, [direction, offset, style, badge === null || badge === void 0 ? void 0 : badge.style]);
94 // =============================== Render ===============================
95 // >>> Title
96 const titleNode = title !== null && title !== void 0 ? title : typeof livingCount === 'string' || typeof livingCount === 'number' ? livingCount : undefined;
97 // >>> Status Text
98 const statusTextNode = isHidden || !text ? null : /*#__PURE__*/React.createElement("span", {
99 className: `${prefixCls}-status-text`
100 }, text);
101 // >>> Display Component
102 const displayNode = !livingCount || typeof livingCount !== 'object' ? undefined : cloneElement(livingCount, oriProps => ({
103 style: Object.assign(Object.assign({}, mergedStyle), oriProps.style)
104 }));
105 // InternalColor
106 const isInternalColor = isPresetColor(color, false);
107 // Shared styles
108 const statusCls = classnames(classNames === null || classNames === void 0 ? void 0 : classNames.indicator, (_a = badge === null || badge === void 0 ? void 0 : badge.classNames) === null || _a === void 0 ? void 0 : _a.indicator, {
109 [`${prefixCls}-status-dot`]: hasStatus,
110 [`${prefixCls}-status-${status}`]: !!status,
111 [`${prefixCls}-color-${color}`]: isInternalColor
112 });
113 const statusStyle = {};
114 if (color && !isInternalColor) {
115 statusStyle.color = color;
116 statusStyle.background = color;
117 }
118 const badgeClassName = classnames(prefixCls, {
119 [`${prefixCls}-status`]: hasStatus,
120 [`${prefixCls}-not-a-wrapper`]: !children,
121 [`${prefixCls}-rtl`]: direction === 'rtl'
122 }, className, rootClassName, badge === null || badge === void 0 ? void 0 : badge.className, (_b = badge === null || badge === void 0 ? void 0 : badge.classNames) === null || _b === void 0 ? void 0 : _b.root, classNames === null || classNames === void 0 ? void 0 : classNames.root, hashId, cssVarCls);
123 // <Badge status="success" />
124 if (!children && hasStatus) {
125 const statusTextColor = mergedStyle.color;
126 return wrapCSSVar( /*#__PURE__*/React.createElement("span", Object.assign({}, restProps, {
127 className: badgeClassName,
128 style: Object.assign(Object.assign(Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.root), (_c = badge === null || badge === void 0 ? void 0 : badge.styles) === null || _c === void 0 ? void 0 : _c.root), mergedStyle)
129 }), /*#__PURE__*/React.createElement("span", {
130 className: statusCls,
131 style: Object.assign(Object.assign(Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.indicator), (_d = badge === null || badge === void 0 ? void 0 : badge.styles) === null || _d === void 0 ? void 0 : _d.indicator), statusStyle)
132 }), text && ( /*#__PURE__*/React.createElement("span", {
133 style: {
134 color: statusTextColor
135 },
136 className: `${prefixCls}-status-text`
137 }, text))));
138 }
139 return wrapCSSVar( /*#__PURE__*/React.createElement("span", Object.assign({
140 ref: ref
141 }, restProps, {
142 className: badgeClassName,
143 style: Object.assign(Object.assign({}, (_e = badge === null || badge === void 0 ? void 0 : badge.styles) === null || _e === void 0 ? void 0 : _e.root), styles === null || styles === void 0 ? void 0 : styles.root)
144 }), children, /*#__PURE__*/React.createElement(CSSMotion, {
145 visible: !isHidden,
146 motionName: `${prefixCls}-zoom`,
147 motionAppear: false,
148 motionDeadline: 1000
149 }, _ref => {
150 let {
151 className: motionClassName,
152 ref: scrollNumberRef
153 } = _ref;
154 var _a, _b;
155 const scrollNumberPrefixCls = getPrefixCls('scroll-number', customizeScrollNumberPrefixCls);
156 const isDot = isDotRef.current;
157 const scrollNumberCls = classnames(classNames === null || classNames === void 0 ? void 0 : classNames.indicator, (_a = badge === null || badge === void 0 ? void 0 : badge.classNames) === null || _a === void 0 ? void 0 : _a.indicator, {
158 [`${prefixCls}-dot`]: isDot,
159 [`${prefixCls}-count`]: !isDot,
160 [`${prefixCls}-count-sm`]: size === 'small',
161 [`${prefixCls}-multiple-words`]: !isDot && displayCount && displayCount.toString().length > 1,
162 [`${prefixCls}-status-${status}`]: !!status,
163 [`${prefixCls}-color-${color}`]: isInternalColor
164 });
165 let scrollNumberStyle = Object.assign(Object.assign(Object.assign({}, styles === null || styles === void 0 ? void 0 : styles.indicator), (_b = badge === null || badge === void 0 ? void 0 : badge.styles) === null || _b === void 0 ? void 0 : _b.indicator), mergedStyle);
166 if (color && !isInternalColor) {
167 scrollNumberStyle = scrollNumberStyle || {};
168 scrollNumberStyle.background = color;
169 }
170 return /*#__PURE__*/React.createElement(ScrollNumber, {
171 prefixCls: scrollNumberPrefixCls,
172 show: !isHidden,
173 motionClassName: motionClassName,
174 className: scrollNumberCls,
175 count: displayCount,
176 title: titleNode,
177 style: scrollNumberStyle,
178 key: "scrollNumber",
179 ref: scrollNumberRef
180 }, displayNode);
181 }), statusTextNode));
182};
183const Badge = /*#__PURE__*/React.forwardRef(InternalBadge);
184Badge.Ribbon = Ribbon;
185if (process.env.NODE_ENV !== 'production') {
186 Badge.displayName = 'Badge';
187}
188export default Badge;
\No newline at end of file