{
- /* eslint-disable no-unused-vars */
+const create = (props: MessageQuickProps) => {
const { duration, afterClose, contextConfig, ...others } = props;
- /* eslint-enable no-unused-vars */
-
const div = document.createElement('div');
document.body.appendChild(div);
- const closeChain = function() {
+ const closeChain = function () {
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.unmountComponentAtNode(div);
document.body.removeChild(div);
afterClose && afterClose();
@@ -136,9 +137,8 @@ const create = props => {
let newContext = contextConfig;
if (!newContext) newContext = ConfigProvider.getContext();
-
- let mask,
- myRef,
+ let mask: ConfigMask | null = null,
+ myRef: ConfigMask,
destroyed = false;
const destroy = () => {
const inc = mask && mask.getInstance();
@@ -146,18 +146,19 @@ const create = props => {
destroyed = true;
};
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.render(
{
- myRef = ref;
+ myRef = ref!;
}}
/>
,
div,
- function() {
+ function () {
mask = myRef;
if (mask && destroyed) {
destroy();
@@ -171,13 +172,17 @@ const create = props => {
};
};
-function handleConfig(config, type) {
- let newConfig = {};
+function isObject(obj: unknown) {
+ return {}.toString.call(obj) === '[object Object]';
+}
+
+function handleConfig(config: OpenProps, type?: MessageQuickProps['type']) {
+ let newConfig: MessageQuickProps = {};
if (typeof config === 'string' || React.isValidElement(config)) {
newConfig.title = config;
} else if (isObject(config)) {
- newConfig = { ...config };
+ newConfig = { ...config } as MessageQuickProps;
}
if (typeof newConfig.duration !== 'number') {
newConfig.duration = 3000;
@@ -189,41 +194,35 @@ function handleConfig(config, type) {
return newConfig;
}
-function isObject(obj) {
- return {}.toString.call(obj) === '[object Object]';
+function close() {
+ if (instance) {
+ instance.destroy();
+ instance = null;
+ }
}
-function open(config, type) {
+function open(config: OpenProps, type?: MessageQuickProps['type']) {
close();
config = handleConfig(config, type);
const timeoutId = guid();
instance = create({ ...config, timeoutId });
- if (config.duration > 0) {
+ if (config.duration! > 0) {
const timeout = setTimeout(close, config.duration);
timeouts[timeoutId] = timeout;
}
}
-function close() {
- if (instance) {
- instance.destroy();
- instance = null;
- }
-}
-
/**
* 创建提示弹层
- * @exportName show
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function show(config) {
+function show(config: OpenProps) {
open(config);
}
/**
* 关闭提示弹层
- * @exportName hide
*/
function hide() {
close();
@@ -231,55 +230,49 @@ function hide() {
/**
* 创建成功提示弹层
- * @exportName success
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function success(config) {
+function success(config: OpenProps) {
open(config, 'success');
}
/**
* 创建警告提示弹层
- * @exportName warning
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function warning(config) {
+function warning(config: OpenProps) {
open(config, 'warning');
}
/**
* 创建错误提示弹层
- * @exportName error
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function error(config) {
+function error(config: OpenProps) {
open(config, 'error');
}
/**
* 创建帮助提示弹层
- * @exportName help
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function help(config) {
+function help(config: OpenProps) {
open(config, 'help');
}
/**
* 创建加载中提示弹层
- * @exportName loading
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function loading(config) {
+function loading(config: OpenProps) {
open(config, 'loading');
}
/**
* 创建通知提示弹层
- * @exportName notice
- * @param {Object} props 属性对象
+ * @param config - 属性对象
*/
-function notice(config) {
+function notice(config: OpenProps) {
open(config, 'notice');
}
@@ -294,13 +287,32 @@ export default {
notice,
};
-export const withContext = WrappedComponent => {
- const HOC = props => {
+export interface ContextMessage {
+ show: (config?: MessageQuickProps) => void;
+ hide: () => void;
+ confirm: (config?: MessageQuickProps) => void;
+ success: (config?: MessageQuickProps) => void;
+ warning: (config?: MessageQuickProps) => void;
+ error: (config?: MessageQuickProps) => void;
+ help: (config?: MessageQuickProps) => void;
+ loading: (config?: MessageQuickProps) => void;
+ notice: (config?: MessageQuickProps) => void;
+}
+export interface WithContextMessageProps {
+ contextMessage: ContextMessage;
+}
+
+export const withContext = (
+ WrappedComponent: JSXElementConstructor
& C
+) => {
+ type Props = React.JSX.LibraryManagedAttributes>;
+ const HOC = (props: Props) => {
return (
{contextConfig => (
show({ ...config, contextConfig }),
hide,
diff --git a/components/message/toast2.jsx b/components/message/toast2.tsx
similarity index 80%
rename from components/message/toast2.jsx
rename to components/message/toast2.tsx
index 6d6ae926e5..278c4750e5 100644
--- a/components/message/toast2.jsx
+++ b/components/message/toast2.tsx
@@ -4,17 +4,23 @@ import ConfigProvider from '../config-provider';
import Animate from '../animate';
import Message from './message';
import { obj, log, guid } from '../util';
+import type {
+ OpenProps,
+ MessageQuickProps,
+ MessageWrapperProps,
+ MessageWrapperItem,
+} from './types';
const config = {
top: 8,
maxCount: 0,
duration: 3000,
};
+export type MessageConfig = Partial;
-const MessageWrapper = props => {
- // eslint-disable-next-line
+const MessageWrapper = (props: MessageWrapperProps) => {
const { prefix = 'next-', dataSource = [] } = props;
- const [, forceUpdate] = useState();
+ const [, forceUpdate] = useState>();
dataSource.forEach(i => {
if (!i.timer) {
@@ -67,10 +73,10 @@ const MessageWrapper = props => {
const ConfigedMessages = ConfigProvider.config(MessageWrapper);
-let messageRootNode;
-let messageList = [];
+let messageRootNode: HTMLDivElement | null;
+let messageList: MessageWrapperProps['dataSource'] = [];
-const createMessage = props => {
+const createMessage = (props: MessageQuickProps & { key?: string }) => {
const { key = guid('message-'), ...others } = props;
if (!messageRootNode) {
messageRootNode = document.createElement('div');
@@ -79,7 +85,7 @@ const createMessage = props => {
const { maxCount, duration } = config;
- const item = {
+ const item: MessageWrapperItem = {
key,
duration,
...others,
@@ -91,6 +97,7 @@ const createMessage = props => {
messageList.shift();
}
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.render(
@@ -109,6 +116,7 @@ const createMessage = props => {
typeof item.onClose === 'function' && item.onClose();
messageList.splice(idx, 1);
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.render(
@@ -120,7 +128,7 @@ const createMessage = props => {
};
};
-function close(key) {
+function close(key?: string) {
if (key) {
const index = messageList.findIndex(item => item.key === key);
messageList.splice(index, 1);
@@ -129,6 +137,7 @@ function close(key) {
}
if (messageRootNode) {
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.render(
@@ -138,13 +147,13 @@ function close(key) {
}
}
-function handleConfig(config, type) {
- let newConfig = {};
+function handleConfig(config: OpenProps, type?: MessageQuickProps['type']) {
+ let newConfig: MessageQuickProps = {};
if (typeof config === 'string' || React.isValidElement(config)) {
newConfig.title = config;
} else if (obj.typeOf(config) === 'Object') {
- newConfig = { ...config };
+ newConfig = { ...config } as MessageQuickProps;
}
if (type) {
@@ -154,8 +163,8 @@ function handleConfig(config, type) {
return newConfig;
}
-function open(type) {
- return config => {
+function open(type?: MessageQuickProps['type']) {
+ return (config: OpenProps) => {
config = handleConfig(config, type);
return createMessage(config);
};
@@ -164,8 +173,9 @@ function open(type) {
function destory() {
if (!messageRootNode) return;
if (messageRootNode) {
+ // eslint-disable-next-line react/no-deprecated
ReactDOM.unmountComponentAtNode(messageRootNode);
- messageRootNode.parentNode.removeChild(messageRootNode);
+ messageRootNode.parentNode!.removeChild(messageRootNode);
messageRootNode = null;
}
}
@@ -180,7 +190,7 @@ export default {
notice: open('notice'),
close,
destory,
- config(...args) {
+ config(...args: MessageConfig[]) {
if (!useState) {
log.warning('need react version > 16.8.0');
return;
diff --git a/components/message/types.ts b/components/message/types.ts
new file mode 100644
index 0000000000..f36af9d9ec
--- /dev/null
+++ b/components/message/types.ts
@@ -0,0 +1,226 @@
+import type React from 'react';
+import type { CommonProps } from '../util';
+import type { OverlayProps } from '../overlay';
+import type { ConsumerState } from '../config-provider/consumer';
+import type { Locale } from '../locale/types';
+
+type HTMLAttributesWeak = Omit, 'title'>;
+
+/**
+ * @api Message
+ */
+export interface MessageProps extends HTMLAttributesWeak, CommonProps {
+ /**
+ * 反馈类型
+ * @en type of message
+ * @defaultValue 'success'
+ */
+ type?: 'success' | 'warning' | 'error' | 'notice' | 'help' | 'loading';
+
+ /**
+ * 反馈外观
+ * @en shape of message
+ * @defaultValue 'inline'
+ */
+ shape?: 'inline' | 'addon' | 'toast';
+
+ /**
+ * 反馈大小
+ * @en size of message
+ * @defaultValue 'medium'
+ */
+ size?: 'medium' | 'large';
+
+ /**
+ * 标题
+ * @en title of message
+ */
+ title?: React.ReactNode;
+
+ /**
+ * 内容,非函数式调用下使用
+ * @en content of message
+ */
+ children?: React.ReactNode;
+
+ /**
+ * 默认是否显示
+ * @en whether the message is visible in default
+ * @defaultValue false
+ */
+ defaultVisible?: boolean;
+
+ /**
+ * 当前是否显示
+ * @en whether the message is visible currently
+ */
+ visible?: boolean;
+
+ /**
+ * 显示的图标类型,会覆盖内部设置的IconType,传false不显示图标
+ * @en type of icon, overriding the internally type of icon
+ */
+ iconType?: string | false;
+
+ /**
+ * 显示关闭按钮
+ * @en whether to show the close button
+ * @defaultValue false
+ */
+ closeable?: boolean;
+
+ /**
+ * 关闭按钮的回调
+ * @en callback function triggered when close
+ * @defaultValue () =\> \{\}
+ */
+ onClose?: () => void;
+
+ /**
+ * 关闭之后调用的函数
+ * @en callback function triggered after closed
+ * @defaultValue () =\> \{\}
+ */
+ afterClose?: () => void;
+
+ /**
+ * 是否开启展开收起动画
+ * @en whether to enable expand and collapse animation
+ * @defaultValue true
+ */
+ animation?: boolean;
+ /**
+ * 多语言文案
+ * @en Locale
+ * @skip
+ */
+ locale?: Locale['Message'];
+}
+
+/**
+ * @api Message.show
+ * @remarks Message.show(props) 提供一个单例的调用方式,配置参数如下(继承 Overlay 的配置):
+ *
+ * ```js
+ * Message.show({
+ * type: 'error',
+ * title: '错误',
+ * content: '请联系相关人员反馈!',
+ * hasMask: true
+ * });
+ * ```
+ * -
+ * `Message.show(props)` provides a singleton call with the following configuration parameters (inheriting `Overlay` configuration):
+ * ```js
+ * Message.show({
+ * type: 'error',
+ * title: 'Error',
+ * content: 'Please contact admin feedback!',
+ * hasMask: true
+ * });
+ * ```
+ */
+export interface MessageQuickProps extends Omit, CommonProps {
+ /**
+ * 反馈类型
+ * @en type of message
+ * @defaultValue 'success'
+ */
+ type?: 'success' | 'warning' | 'error' | 'notice' | 'help' | 'loading';
+
+ /**
+ * 反馈大小
+ * @en size of message
+ * @defaultValue 'medium'
+ */
+ size?: 'medium' | 'large';
+ /**
+ * 标题
+ * @en title of message
+ */
+ title?: React.ReactNode;
+
+ /**
+ * 内容,函数式调用下使用
+ * @en content of message
+ */
+ content?: React.ReactNode;
+ /**
+ * 弹层对齐方式,详情见 Overlay align
+ * @en alignment reference Overlay
+ * @defaultValue 'tc tc'
+ */
+ align?: string | boolean;
+
+ /**
+ * 弹层相对于参照元素定位的微调
+ * @en offset after positioned
+ * @defaultValue [0, 0]
+ */
+ offset?: Array;
+ /**
+ * 是否显示遮罩
+ * @en whether to have a mask
+ * @defaultValue false
+ */
+ hasMask?: boolean;
+
+ /**
+ * 显示持续时间,0表示一直存在,以毫秒为单位
+ * @en show duration, 0 means always present, in milliseconds
+ * @defaultValue 3000
+ */
+ duration?: number;
+ /**
+ * @skip
+ */
+ timeoutId?: string;
+
+ /**
+ * 显示关闭按钮
+ * @en whether to show the close button
+ * @defaultValue false
+ */
+ closeable?: boolean;
+
+ /**
+ * 关闭按钮的回调
+ * @en callback function triggered when close
+ * @defaultValue () =\> \{\}
+ */
+ onClose?: () => void;
+
+ /**
+ * 关闭之后调用的函数
+ * @en callback function triggered after closed
+ * @defaultValue () =\> \{\}
+ */
+ afterClose?: () => void;
+
+ /**
+ * 是否开启展开收起动画
+ * @en whether to enable expand and collapse animation
+ * @defaultValue true
+ */
+ animation?: boolean;
+ /**
+ * 透传到弹层组件的属性对象
+ * @en props of Overlay
+ */
+ overlayProps?: OverlayProps;
+ /**
+ * @skip
+ */
+ contextConfig?: ConsumerState;
+}
+
+export type OpenProps = string | React.ReactElement | MessageQuickProps;
+
+export interface MessageWrapperItem extends MessageQuickProps {
+ timer?: ReturnType;
+ key: string;
+}
+export interface MessageWrapperProps {
+ prefix?: MessageQuickProps['prefix'];
+ dataSource: Array;
+}