init
This commit is contained in:
35
uni_modules/nutui-uni/components/notify/index.scss
Normal file
35
uni_modules/nutui-uni/components/notify/index.scss
Normal file
@@ -0,0 +1,35 @@
|
||||
@import "../popup/index";
|
||||
|
||||
.nut-notify {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: $notify-height;
|
||||
padding: $notify-padding;
|
||||
font-size: $notify-font-size;
|
||||
line-height: $notify-line-height;
|
||||
color: $notify-text-color;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
|
||||
&--base {
|
||||
background: $notify-base-background-color;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
background: $notify-primary-background-color;
|
||||
}
|
||||
|
||||
&--success {
|
||||
background: $notify-success-background-color;
|
||||
}
|
||||
|
||||
&--danger {
|
||||
background: $notify-danger-background-color;
|
||||
}
|
||||
|
||||
&--warning {
|
||||
background: $notify-warning-background-color;
|
||||
}
|
||||
}
|
||||
2
uni_modules/nutui-uni/components/notify/index.ts
Normal file
2
uni_modules/nutui-uni/components/notify/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './notify'
|
||||
export * from './types'
|
||||
100
uni_modules/nutui-uni/components/notify/notify.ts
Normal file
100
uni_modules/nutui-uni/components/notify/notify.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import { CLICK_EVENT, CLOSE_EVENT, CLOSED_EVENT, UPDATE_VISIBLE_EVENT } from '../_constants'
|
||||
import { commonProps, isBoolean, makeNumberProp, makeNumericProp, makeStringProp } from '../_utils'
|
||||
import type { NotifyOptions, NotifyPosition, NotifyType } from './types'
|
||||
|
||||
export const notifyDefaultOptionsKey = '__NOTIFY_OPTIONS__'
|
||||
|
||||
export const notifyDefaultOptions: Required<Pick<
|
||||
NotifyOptions,
|
||||
'visible' | 'type' | 'msg' | 'position' | 'duration' | 'zIndex'
|
||||
>> = {
|
||||
visible: false,
|
||||
type: 'danger',
|
||||
msg: '',
|
||||
position: 'top',
|
||||
duration: 3000,
|
||||
zIndex: 9999,
|
||||
} as const
|
||||
|
||||
export const notifyProps = {
|
||||
...commonProps,
|
||||
/**
|
||||
* @description 显示与否
|
||||
*/
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: notifyDefaultOptions.visible,
|
||||
},
|
||||
/**
|
||||
* @description 配置注入的key
|
||||
*/
|
||||
selector: String,
|
||||
/**
|
||||
* @description 提示的信息类型,可选值为`base` `primary` `success` `danger` `warning`
|
||||
*/
|
||||
type: makeStringProp<NotifyType>(notifyDefaultOptions.type),
|
||||
/**
|
||||
* @description 展示文案,支持通过`\n`换行
|
||||
*/
|
||||
msg: makeStringProp(notifyDefaultOptions.msg),
|
||||
/**
|
||||
* @description 自定义位置,可选值为 `top` `bottom`
|
||||
*/
|
||||
position: makeStringProp<NotifyPosition>(notifyDefaultOptions.position),
|
||||
/**
|
||||
* @description 展示时长(ms),值为 0 时,notify 不会消失
|
||||
*/
|
||||
duration: makeNumberProp(notifyDefaultOptions.duration),
|
||||
/**
|
||||
* @description 自定义类名
|
||||
*/
|
||||
className: makeStringProp(''),
|
||||
/**
|
||||
* @description 组件z-index
|
||||
*/
|
||||
zIndex: makeNumberProp(notifyDefaultOptions.zIndex),
|
||||
/**
|
||||
* @description 字体颜色
|
||||
*/
|
||||
customColor: makeStringProp(''),
|
||||
/**
|
||||
* @description 背景颜色
|
||||
*/
|
||||
background: makeStringProp(''),
|
||||
/**
|
||||
* @description 是否留出顶部安全距离(默认为状态栏高度)
|
||||
*/
|
||||
safeAreaInsetTop: Boolean,
|
||||
/**
|
||||
* @description 是否留出底部安全距离(启用后通过 `safeHeight` 指定距离)
|
||||
*/
|
||||
safeAreaInsetBottom: Boolean,
|
||||
/**
|
||||
* @description 自定义安全距离
|
||||
*/
|
||||
safeHeight: makeNumericProp(''),
|
||||
/**
|
||||
* @description 点击时的回调函数
|
||||
*/
|
||||
onClick: Function,
|
||||
/**
|
||||
* @description 关闭时的回调函数
|
||||
*/
|
||||
onClose: Function,
|
||||
/**
|
||||
* @description 关闭动画完成时回调函数
|
||||
*/
|
||||
onClosed: Function,
|
||||
}
|
||||
|
||||
export type NotifyProps = ExtractPropTypes<typeof notifyProps>
|
||||
|
||||
export const notifyEmits = {
|
||||
[UPDATE_VISIBLE_EVENT]: (value: boolean) => isBoolean(value),
|
||||
[CLICK_EVENT]: () => true,
|
||||
[CLOSE_EVENT]: () => true,
|
||||
[CLOSED_EVENT]: () => true,
|
||||
}
|
||||
|
||||
export type NotifyEmits = typeof notifyEmits
|
||||
240
uni_modules/nutui-uni/components/notify/notify.vue
Normal file
240
uni_modules/nutui-uni/components/notify/notify.vue
Normal file
@@ -0,0 +1,240 @@
|
||||
<script lang="ts" setup>
|
||||
import type { CSSProperties, Ref } from 'vue'
|
||||
import { computed, defineComponent, inject, onBeforeUnmount, ref, useSlots, watch } from 'vue'
|
||||
import { CLICK_EVENT, CLOSE_EVENT, CLOSED_EVENT, PREFIX, UPDATE_VISIBLE_EVENT } from '../_constants'
|
||||
import { cloneDeep, getMainClass, getMainStyle, pxCheck } from '../_utils'
|
||||
import NutPopup from '../popup/popup.vue'
|
||||
import { notifyDefaultOptions, notifyDefaultOptionsKey, notifyEmits, notifyProps } from './notify'
|
||||
import type { NotifyOptions, NotifyType } from './types'
|
||||
|
||||
const props = defineProps(notifyProps)
|
||||
|
||||
const emit = defineEmits(notifyEmits)
|
||||
|
||||
const slots = useSlots()
|
||||
|
||||
const notifyOptionsKey = `${notifyDefaultOptionsKey}${props.selector || ''}`
|
||||
const injectNotifyOptions: Ref<NotifyOptions> = inject(notifyOptionsKey, ref(cloneDeep(notifyDefaultOptions)))
|
||||
|
||||
const innerVisible = ref(false)
|
||||
|
||||
const notifyOptions = ref<NotifyOptions>(cloneDeep(props))
|
||||
|
||||
const classes = computed(() => {
|
||||
const { type, className } = notifyOptions.value
|
||||
|
||||
const value = {
|
||||
[`nut-notify--${type}`]: true,
|
||||
}
|
||||
|
||||
if (className) {
|
||||
value[className] = true
|
||||
}
|
||||
|
||||
return getMainClass(props, componentName, value)
|
||||
})
|
||||
|
||||
const styles = computed(() => {
|
||||
const value: CSSProperties = {}
|
||||
|
||||
const { customColor, background } = notifyOptions.value
|
||||
|
||||
if (customColor) {
|
||||
value.color = customColor
|
||||
}
|
||||
|
||||
if (background) {
|
||||
value.background = background
|
||||
}
|
||||
|
||||
return getMainStyle(props, value)
|
||||
})
|
||||
|
||||
const wrapperStyles = computed(() => {
|
||||
const value: CSSProperties = {}
|
||||
|
||||
const { position, safeAreaInsetTop, safeAreaInsetBottom, safeHeight } = notifyOptions.value
|
||||
|
||||
if (position === 'top') {
|
||||
if (safeAreaInsetTop) {
|
||||
if (safeHeight) {
|
||||
value.top = pxCheck(safeHeight)
|
||||
}
|
||||
else {
|
||||
value.top = `${uni.getSystemInfoSync().statusBarHeight}px`
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (position === 'bottom') {
|
||||
if (safeAreaInsetBottom) {
|
||||
if (safeHeight) {
|
||||
value.bottom = pxCheck(safeHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
})
|
||||
|
||||
let timer: NodeJS.Timeout | null = null
|
||||
|
||||
function startTimer() {
|
||||
timer = setTimeout(() => {
|
||||
hide()
|
||||
}, notifyOptions.value.duration)
|
||||
}
|
||||
|
||||
function destroyTimer() {
|
||||
if (timer == null)
|
||||
return
|
||||
|
||||
clearTimeout(timer)
|
||||
timer = null
|
||||
}
|
||||
|
||||
function show(type: NotifyType, msg: string, options?: NotifyOptions) {
|
||||
destroyTimer()
|
||||
|
||||
notifyOptions.value = Object.assign(cloneDeep(notifyDefaultOptions), {
|
||||
visible: true,
|
||||
type,
|
||||
msg,
|
||||
}, options)
|
||||
|
||||
innerVisible.value = true
|
||||
|
||||
if (notifyOptions.value.duration! > 0)
|
||||
startTimer()
|
||||
}
|
||||
|
||||
function legacyShow(options: NotifyOptions) {
|
||||
show(notifyDefaultOptions.type, options.msg || notifyDefaultOptions.msg, options)
|
||||
}
|
||||
|
||||
function showPrimary(msg: string, options?: NotifyOptions) {
|
||||
show('primary', msg, options)
|
||||
}
|
||||
|
||||
function showSuccess(msg: string, options?: NotifyOptions) {
|
||||
show('success', msg, options)
|
||||
}
|
||||
|
||||
function showDanger(msg: string, options?: NotifyOptions) {
|
||||
show('danger', msg, options)
|
||||
}
|
||||
|
||||
function showWarning(msg: string, options?: NotifyOptions) {
|
||||
show('warning', msg, options)
|
||||
}
|
||||
|
||||
function showCustom(msg: string, options?: NotifyOptions) {
|
||||
show('custom', msg, options)
|
||||
}
|
||||
|
||||
function hide() {
|
||||
destroyTimer()
|
||||
|
||||
innerVisible.value = false
|
||||
notifyOptions.value.visible = false
|
||||
|
||||
emit(UPDATE_VISIBLE_EVENT, false)
|
||||
emit(CLOSE_EVENT)
|
||||
|
||||
if (notifyOptions.value.onClose) {
|
||||
notifyOptions.value.onClose()
|
||||
}
|
||||
}
|
||||
|
||||
function handleClosed() {
|
||||
emit(CLOSED_EVENT)
|
||||
|
||||
if (notifyOptions.value.onClosed) {
|
||||
notifyOptions.value.onClosed()
|
||||
}
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
emit(CLICK_EVENT)
|
||||
|
||||
if (notifyOptions.value.onClick) {
|
||||
notifyOptions.value.onClick()
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => props, (value) => {
|
||||
notifyOptions.value = Object.assign(cloneDeep(notifyDefaultOptions), value)
|
||||
|
||||
if (value.visible)
|
||||
show(notifyOptions.value.type!, notifyOptions.value.msg!, notifyOptions.value)
|
||||
else
|
||||
hide()
|
||||
}, { deep: true })
|
||||
|
||||
watch(injectNotifyOptions, (value) => {
|
||||
notifyOptions.value = Object.assign(cloneDeep(notifyDefaultOptions), value)
|
||||
|
||||
if (value.visible)
|
||||
show(notifyOptions.value.type!, notifyOptions.value.msg!, notifyOptions.value)
|
||||
else
|
||||
hide()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
destroyTimer()
|
||||
})
|
||||
|
||||
defineExpose({
|
||||
showNotify: legacyShow,
|
||||
hideNotify: hide,
|
||||
|
||||
show,
|
||||
primary: showPrimary,
|
||||
success: showSuccess,
|
||||
danger: showDanger,
|
||||
warning: showWarning,
|
||||
custom: showCustom,
|
||||
hide,
|
||||
})
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const componentName = `${PREFIX}-notify`
|
||||
|
||||
export default defineComponent({
|
||||
name: componentName,
|
||||
options: {
|
||||
virtualHost: true,
|
||||
addGlobalClass: true,
|
||||
styleIsolation: 'shared',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NutPopup
|
||||
v-model:visible="innerVisible"
|
||||
:custom-style="wrapperStyles"
|
||||
:position="notifyOptions.position"
|
||||
:overlay="false"
|
||||
:z-index="notifyOptions.zIndex"
|
||||
:safe-area-inset-top="false"
|
||||
:safe-area-inset-bottom="false"
|
||||
@closed="handleClosed"
|
||||
>
|
||||
<view
|
||||
:class="classes"
|
||||
:style="styles"
|
||||
@click="handleClick"
|
||||
>
|
||||
<slot v-if="slots.default" />
|
||||
|
||||
<template v-else>
|
||||
{{ notifyOptions.msg }}
|
||||
</template>
|
||||
</view>
|
||||
</NutPopup>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./index";
|
||||
</style>
|
||||
113
uni_modules/nutui-uni/components/notify/types.ts
Normal file
113
uni_modules/nutui-uni/components/notify/types.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
export const notifyPosition = ['top', 'bottom'] as const
|
||||
export type NotifyPosition = (typeof notifyPosition)[number]
|
||||
|
||||
export const notifyType = ['base', 'primary', 'success', 'danger', 'warning', 'custom'] as const
|
||||
export type NotifyType = (typeof notifyType)[number]
|
||||
|
||||
export interface NotifyOptions {
|
||||
/**
|
||||
* @description 显示与否
|
||||
*/
|
||||
visible?: boolean
|
||||
/**
|
||||
* @description 提示的信息类型,可选值为`base` `primary` `success` `danger` `warning`
|
||||
*/
|
||||
type?: NotifyType
|
||||
/**
|
||||
* @description 展示文案,支持通过`\n`换行
|
||||
*/
|
||||
msg?: string
|
||||
/**
|
||||
* @description 自定义位置,可选值为 `top` `bottom`
|
||||
*/
|
||||
position?: NotifyPosition
|
||||
/**
|
||||
* @description 展示时长(ms),值为 0 时,notify 不会消失
|
||||
*/
|
||||
duration?: number
|
||||
/**
|
||||
* @description 自定义类名
|
||||
*/
|
||||
className?: string
|
||||
/**
|
||||
* @description 组件z-index
|
||||
*/
|
||||
zIndex?: number
|
||||
/**
|
||||
* @description 字体颜色
|
||||
*/
|
||||
customColor?: string
|
||||
/**
|
||||
* @description 背景颜色
|
||||
*/
|
||||
background?: string
|
||||
/**
|
||||
* @description 是否留出顶部安全距离(默认为状态栏高度)
|
||||
*/
|
||||
safeAreaInsetTop?: boolean
|
||||
/**
|
||||
* @description 是否留出底部安全距离(启用后通过 `safeHeight` 指定距离)
|
||||
*/
|
||||
safeAreaInsetBottom?: boolean
|
||||
/**
|
||||
* @description 自定义安全距离
|
||||
*/
|
||||
safeHeight?: number | string
|
||||
/**
|
||||
* @description 点击时的回调函数
|
||||
*/
|
||||
// eslint-disable-next-line ts/no-unsafe-function-type
|
||||
onClick?: Function
|
||||
/**
|
||||
* @description 关闭时的回调函数
|
||||
*/
|
||||
// eslint-disable-next-line ts/no-unsafe-function-type
|
||||
onClose?: Function
|
||||
/**
|
||||
* @description 关闭动画完成时回调函数
|
||||
*/
|
||||
// eslint-disable-next-line ts/no-unsafe-function-type
|
||||
onClosed?: Function
|
||||
}
|
||||
|
||||
export interface NotifyInst {
|
||||
/**
|
||||
* @deprecated 使用`show`、`primary`、`success`、`danger`、`warning`代替
|
||||
* @description 显示通知
|
||||
*/
|
||||
showNotify: (options: NotifyOptions) => void
|
||||
/**
|
||||
* @deprecated 使用`hide`代替
|
||||
* @description 隐藏通知
|
||||
*/
|
||||
hideNotify: () => void
|
||||
|
||||
/**
|
||||
* @description 显示通知
|
||||
*/
|
||||
show: (type: NotifyType, msg: string, options?: NotifyOptions) => void
|
||||
/**
|
||||
* @description 主要通知
|
||||
*/
|
||||
primary: (msg: string, options?: NotifyOptions) => void
|
||||
/**
|
||||
* @description 成功通知
|
||||
*/
|
||||
success: (msg: string, options?: NotifyOptions) => void
|
||||
/**
|
||||
* @description 危险通知
|
||||
*/
|
||||
danger: (msg: string, options?: NotifyOptions) => void
|
||||
/**
|
||||
* @description 警告通知
|
||||
*/
|
||||
warning: (msg: string, options?: NotifyOptions) => void
|
||||
/**
|
||||
* @description 自定义通知
|
||||
*/
|
||||
custom: (msg: string, options?: NotifyOptions) => void
|
||||
/**
|
||||
* @description 隐藏通知
|
||||
*/
|
||||
hide: () => void
|
||||
}
|
||||
62
uni_modules/nutui-uni/components/notify/use-notify.ts
Normal file
62
uni_modules/nutui-uni/components/notify/use-notify.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { provide, ref } from 'vue'
|
||||
import { cloneDeep } from '../_utils'
|
||||
import { notifyDefaultOptions, notifyDefaultOptionsKey } from './notify'
|
||||
import type { NotifyInst, NotifyOptions, NotifyType } from './types'
|
||||
|
||||
export function useNotify(selector = ''): NotifyInst {
|
||||
const notifyOptionsKey = `${notifyDefaultOptionsKey}${selector || ''}`
|
||||
const notifyOptions = ref<NotifyOptions>(cloneDeep(notifyDefaultOptions))
|
||||
|
||||
provide(notifyOptionsKey, notifyOptions)
|
||||
|
||||
function show(type: NotifyType, msg: string, options?: NotifyOptions) {
|
||||
notifyOptions.value = Object.assign({
|
||||
visible: true,
|
||||
type,
|
||||
msg,
|
||||
}, options)
|
||||
}
|
||||
|
||||
function legacyShow(options: NotifyOptions) {
|
||||
show(notifyDefaultOptions.type, options.msg || notifyDefaultOptions.msg, options)
|
||||
}
|
||||
|
||||
function showPrimary(msg: string, options?: NotifyOptions) {
|
||||
show('primary', msg, options)
|
||||
}
|
||||
|
||||
function showSuccess(msg: string, options?: NotifyOptions) {
|
||||
show('success', msg, options)
|
||||
}
|
||||
|
||||
function showDanger(msg: string, options?: NotifyOptions) {
|
||||
show('danger', msg, options)
|
||||
}
|
||||
|
||||
function showWarning(msg: string, options?: NotifyOptions) {
|
||||
show('warning', msg, options)
|
||||
}
|
||||
|
||||
function showCustom(msg: string, options?: NotifyOptions) {
|
||||
show('custom', msg, options)
|
||||
}
|
||||
|
||||
function hide() {
|
||||
notifyOptions.value = Object.assign(cloneDeep(notifyOptions.value), {
|
||||
visible: false,
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
showNotify: legacyShow,
|
||||
hideNotify: hide,
|
||||
|
||||
show,
|
||||
primary: showPrimary,
|
||||
success: showSuccess,
|
||||
danger: showDanger,
|
||||
warning: showWarning,
|
||||
custom: showCustom,
|
||||
hide,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user