mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
types(Toast): add Toast method typing (#8095)
This commit is contained in:
parent
7332e5201c
commit
02669ad025
@ -30,8 +30,9 @@
|
|||||||
</demo-block>
|
</demo-block>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script lang="ts">
|
||||||
import { useTranslate } from '@demo/use-translate';
|
import { useTranslate } from '@demo/use-translate';
|
||||||
|
import type { LoadingType } from '../../loading';
|
||||||
import Toast from '..';
|
import Toast from '..';
|
||||||
|
|
||||||
const i18n = {
|
const i18n = {
|
||||||
@ -40,7 +41,7 @@ const i18n = {
|
|||||||
text: '提示内容',
|
text: '提示内容',
|
||||||
text2: '成功文案',
|
text2: '成功文案',
|
||||||
text3: '失败文案',
|
text3: '失败文案',
|
||||||
text4: (second) => `倒计时 ${second} 秒`,
|
text4: (second: number) => `倒计时 ${second} 秒`,
|
||||||
title1: '文字提示',
|
title1: '文字提示',
|
||||||
title2: '加载提示',
|
title2: '加载提示',
|
||||||
title3: '成功/失败提示',
|
title3: '成功/失败提示',
|
||||||
@ -58,7 +59,7 @@ const i18n = {
|
|||||||
text: 'Some messages',
|
text: 'Some messages',
|
||||||
text2: 'Success',
|
text2: 'Success',
|
||||||
text3: 'Fail',
|
text3: 'Fail',
|
||||||
text4: (second) => `${second} seconds`,
|
text4: (second: number) => `${second} seconds`,
|
||||||
title1: 'Text',
|
title1: 'Text',
|
||||||
title2: 'Loading',
|
title2: 'Loading',
|
||||||
title3: 'Success/Fail',
|
title3: 'Success/Fail',
|
||||||
@ -77,7 +78,7 @@ export default {
|
|||||||
setup() {
|
setup() {
|
||||||
const t = useTranslate(i18n);
|
const t = useTranslate(i18n);
|
||||||
|
|
||||||
const showLoadingToast = (loadingType) => {
|
const showLoadingToast = (loadingType: LoadingType) => {
|
||||||
Toast.loading({
|
Toast.loading({
|
||||||
forbidClick: true,
|
forbidClick: true,
|
||||||
message: t('loading'),
|
message: t('loading'),
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
import { ref, watch, getCurrentInstance } from 'vue';
|
|
||||||
import { isObject, inBrowser } from '../utils';
|
|
||||||
import { mountComponent, usePopupState } from '../utils/mount-component';
|
|
||||||
import VanToast from './Toast';
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
icon: '',
|
|
||||||
type: 'text',
|
|
||||||
message: '',
|
|
||||||
className: '',
|
|
||||||
overlay: false,
|
|
||||||
onClose: null,
|
|
||||||
onOpened: null,
|
|
||||||
duration: 2000,
|
|
||||||
teleport: 'body',
|
|
||||||
iconPrefix: undefined,
|
|
||||||
position: 'middle',
|
|
||||||
transition: 'van-fade',
|
|
||||||
forbidClick: false,
|
|
||||||
loadingType: undefined,
|
|
||||||
overlayClass: '',
|
|
||||||
overlayStyle: null,
|
|
||||||
closeOnClick: false,
|
|
||||||
closeOnClickOverlay: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
// default options of specific type
|
|
||||||
let defaultOptionsMap = {};
|
|
||||||
let queue = [];
|
|
||||||
let allowMultiple = false;
|
|
||||||
let currentOptions = {
|
|
||||||
...defaultOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseOptions(message) {
|
|
||||||
if (isObject(message)) {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
return { message };
|
|
||||||
}
|
|
||||||
|
|
||||||
function createInstance() {
|
|
||||||
const { instance, unmount } = mountComponent({
|
|
||||||
setup() {
|
|
||||||
const message = ref();
|
|
||||||
const { open, state, close, toggle } = usePopupState();
|
|
||||||
|
|
||||||
const onClosed = () => {
|
|
||||||
if (allowMultiple) {
|
|
||||||
queue = queue.filter((item) => item !== instance);
|
|
||||||
unmount();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(message, (value) => {
|
|
||||||
state.message = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
getCurrentInstance().render = () => (
|
|
||||||
<VanToast
|
|
||||||
{...{
|
|
||||||
...state,
|
|
||||||
onClosed,
|
|
||||||
'onUpdate:show': toggle,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
open,
|
|
||||||
clear: close,
|
|
||||||
message,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getInstance() {
|
|
||||||
/* istanbul ignore if */
|
|
||||||
if (!inBrowser) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!queue.length || allowMultiple) {
|
|
||||||
const instance = createInstance();
|
|
||||||
queue.push(instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return queue[queue.length - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
function Toast(options = {}) {
|
|
||||||
const toast = getInstance();
|
|
||||||
|
|
||||||
options = parseOptions(options);
|
|
||||||
options = {
|
|
||||||
...currentOptions,
|
|
||||||
...defaultOptionsMap[options.type || currentOptions.type],
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
toast.open(options);
|
|
||||||
|
|
||||||
return toast;
|
|
||||||
}
|
|
||||||
|
|
||||||
const createMethod = (type) => (options) =>
|
|
||||||
Toast({
|
|
||||||
type,
|
|
||||||
...parseOptions(options),
|
|
||||||
});
|
|
||||||
|
|
||||||
['loading', 'success', 'fail'].forEach((method) => {
|
|
||||||
Toast[method] = createMethod(method);
|
|
||||||
});
|
|
||||||
|
|
||||||
Toast.clear = (all) => {
|
|
||||||
if (queue.length) {
|
|
||||||
if (all) {
|
|
||||||
queue.forEach((toast) => {
|
|
||||||
toast.clear();
|
|
||||||
});
|
|
||||||
queue = [];
|
|
||||||
} else if (!allowMultiple) {
|
|
||||||
queue[0].clear();
|
|
||||||
} else {
|
|
||||||
queue.shift().clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Toast.setDefaultOptions = (type, options) => {
|
|
||||||
if (typeof type === 'string') {
|
|
||||||
defaultOptionsMap[type] = options;
|
|
||||||
} else {
|
|
||||||
Object.assign(currentOptions, type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Toast.resetDefaultOptions = (type) => {
|
|
||||||
if (typeof type === 'string') {
|
|
||||||
defaultOptionsMap[type] = null;
|
|
||||||
} else {
|
|
||||||
currentOptions = { ...defaultOptions };
|
|
||||||
defaultOptionsMap = {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Toast.allowMultiple = (value = true) => {
|
|
||||||
allowMultiple = value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Toast.install = (app) => {
|
|
||||||
app.use(VanToast);
|
|
||||||
app.config.globalProperties.$toast = Toast;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Toast;
|
|
187
src/toast/index.tsx
Normal file
187
src/toast/index.tsx
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
import { ref, App, TeleportProps, getCurrentInstance } from 'vue';
|
||||||
|
import { isObject, inBrowser } from '../utils';
|
||||||
|
import { mountComponent, usePopupState } from '../utils/mount-component';
|
||||||
|
import VanToast, { ToastType, ToastPosition } from './Toast';
|
||||||
|
import type { LoadingType } from '../loading';
|
||||||
|
|
||||||
|
export type ToastOptions = {
|
||||||
|
icon?: string;
|
||||||
|
type?: ToastType;
|
||||||
|
mask?: boolean;
|
||||||
|
message?: string | number;
|
||||||
|
onClose?: () => void;
|
||||||
|
onOpened?: () => void;
|
||||||
|
overlay?: boolean;
|
||||||
|
duration?: number;
|
||||||
|
teleport?: TeleportProps['to'];
|
||||||
|
position?: ToastPosition;
|
||||||
|
className?: any;
|
||||||
|
transition?: string;
|
||||||
|
iconPrefix?: string;
|
||||||
|
loadingType?: LoadingType;
|
||||||
|
forbidClick?: boolean;
|
||||||
|
closeOnClick?: boolean;
|
||||||
|
overlayClass?: any;
|
||||||
|
overlayStyle?: Record<string, any>;
|
||||||
|
closeOnClickOverlay?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const defaultOptions: ToastOptions = {
|
||||||
|
icon: '',
|
||||||
|
type: 'text',
|
||||||
|
message: '',
|
||||||
|
className: '',
|
||||||
|
overlay: false,
|
||||||
|
onClose: undefined,
|
||||||
|
onOpened: undefined,
|
||||||
|
duration: 2000,
|
||||||
|
teleport: 'body',
|
||||||
|
iconPrefix: undefined,
|
||||||
|
position: 'middle',
|
||||||
|
transition: 'van-fade',
|
||||||
|
forbidClick: false,
|
||||||
|
loadingType: undefined,
|
||||||
|
overlayClass: '',
|
||||||
|
overlayStyle: undefined,
|
||||||
|
closeOnClick: false,
|
||||||
|
closeOnClickOverlay: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let queue: any[] = [];
|
||||||
|
let allowMultiple = false;
|
||||||
|
let currentOptions = { ...defaultOptions };
|
||||||
|
|
||||||
|
// default options of specific type
|
||||||
|
let defaultOptionsMap: Record<string, ToastOptions | null> = {};
|
||||||
|
|
||||||
|
function parseOptions(message: string | ToastOptions): ToastOptions {
|
||||||
|
if (isObject(message)) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
return { message };
|
||||||
|
}
|
||||||
|
|
||||||
|
function createInstance() {
|
||||||
|
const { instance, unmount } = mountComponent({
|
||||||
|
setup() {
|
||||||
|
const message = ref();
|
||||||
|
const { open, state, close, toggle } = usePopupState();
|
||||||
|
|
||||||
|
const onClosed = () => {
|
||||||
|
if (allowMultiple) {
|
||||||
|
queue = queue.filter((item) => item !== instance);
|
||||||
|
unmount();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const render = () => {
|
||||||
|
const attrs: Record<string, unknown> = {
|
||||||
|
...state,
|
||||||
|
onClosed,
|
||||||
|
'onUpdate:show': toggle,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (message.value) {
|
||||||
|
attrs.message = message.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <VanToast {...attrs} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
// rewrite render function
|
||||||
|
(getCurrentInstance() as any).render = render;
|
||||||
|
|
||||||
|
return {
|
||||||
|
open,
|
||||||
|
clear: close,
|
||||||
|
message,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInstance() {
|
||||||
|
/* istanbul ignore if */
|
||||||
|
if (!inBrowser) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!queue.length || allowMultiple) {
|
||||||
|
const instance = createInstance();
|
||||||
|
queue.push(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return queue[queue.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
function Toast(options: string | ToastOptions = {}) {
|
||||||
|
const toast = getInstance();
|
||||||
|
const parsedOptions = parseOptions(options);
|
||||||
|
|
||||||
|
toast.open({
|
||||||
|
...currentOptions,
|
||||||
|
...defaultOptionsMap[parsedOptions.type || currentOptions.type!],
|
||||||
|
...parsedOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
return toast;
|
||||||
|
}
|
||||||
|
|
||||||
|
const createMethod = (type: ToastType) => (options: string | ToastOptions) =>
|
||||||
|
Toast({
|
||||||
|
type,
|
||||||
|
...parseOptions(options),
|
||||||
|
});
|
||||||
|
|
||||||
|
Toast.loading = createMethod('loading');
|
||||||
|
Toast.success = createMethod('success');
|
||||||
|
Toast.fail = createMethod('fail');
|
||||||
|
|
||||||
|
Toast.clear = (all?: boolean) => {
|
||||||
|
if (queue.length) {
|
||||||
|
if (all) {
|
||||||
|
queue.forEach((toast) => {
|
||||||
|
toast.clear();
|
||||||
|
});
|
||||||
|
queue = [];
|
||||||
|
} else if (!allowMultiple) {
|
||||||
|
queue[0].clear();
|
||||||
|
} else {
|
||||||
|
queue.shift().clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function setDefaultOptions(options: ToastOptions): void;
|
||||||
|
function setDefaultOptions(type: ToastType, options: ToastOptions): void;
|
||||||
|
function setDefaultOptions(type: ToastType | ToastOptions, options?: any) {
|
||||||
|
if (typeof type === 'string') {
|
||||||
|
defaultOptionsMap[type] = options;
|
||||||
|
} else {
|
||||||
|
Object.assign(currentOptions, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.setDefaultOptions = setDefaultOptions;
|
||||||
|
|
||||||
|
Toast.resetDefaultOptions = (type?: ToastType) => {
|
||||||
|
if (typeof type === 'string') {
|
||||||
|
defaultOptionsMap[type] = null;
|
||||||
|
} else {
|
||||||
|
currentOptions = { ...defaultOptions };
|
||||||
|
defaultOptionsMap = {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Toast.allowMultiple = (value = true) => {
|
||||||
|
allowMultiple = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
Toast.install = (app: App) => {
|
||||||
|
app.use(VanToast as any);
|
||||||
|
app.config.globalProperties.$toast = Toast;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Toast;
|
Loading…
x
Reference in New Issue
Block a user