mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-18 12:34:25 +08:00
refactor(popconfirm): ts
This commit is contained in:
parent
76fdc91e3d
commit
08549be2e4
@ -1,105 +0,0 @@
|
||||
import { h, ref, defineComponent, provide, getCurrentInstance } from 'vue'
|
||||
import { NPopover } from '../../popover'
|
||||
import { omit, keep } from '../../_utils'
|
||||
import { useTheme } from '../../_mixins'
|
||||
import { popconfirmLight } from '../styles'
|
||||
import PopconfirmPanel from './PopconfirmPanel.vue'
|
||||
import style from './styles/index.cssr.js'
|
||||
|
||||
const panelProps = Object.keys(PopconfirmPanel.props)
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Popconfirm',
|
||||
props: {
|
||||
...NPopover.props,
|
||||
positiveText: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
negativeText: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
trigger: {
|
||||
type: String,
|
||||
default: 'click'
|
||||
},
|
||||
onPositiveClick: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
onNegativeClick: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const themeRef = useTheme(
|
||||
'Popconfirm',
|
||||
'Popconfirm',
|
||||
style,
|
||||
popconfirmLight,
|
||||
props
|
||||
)
|
||||
provide('NPopconfirm', getCurrentInstance().proxy)
|
||||
return {
|
||||
mergedTheme: themeRef,
|
||||
popoverRef: ref(null)
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { $slots: slots, $props: props, mergedTheme } = this
|
||||
return h(
|
||||
NPopover,
|
||||
{
|
||||
...omit(props, panelProps, {
|
||||
unstableTheme: mergedTheme.peers.Popover,
|
||||
unstableThemeOverrides: mergedTheme.overrides.Popover
|
||||
}),
|
||||
class: 'n-popconfirm',
|
||||
ref: 'popoverRef'
|
||||
},
|
||||
{
|
||||
trigger: slots.activator || slots.trigger,
|
||||
default: () =>
|
||||
h(
|
||||
PopconfirmPanel,
|
||||
{
|
||||
...keep(props, panelProps),
|
||||
onPositiveClick: () => {
|
||||
const {
|
||||
onPositiveClick = () => true,
|
||||
'onUpdate:show': onUpdateShow
|
||||
} = this
|
||||
Promise.resolve(onPositiveClick()).then((value) => {
|
||||
if (value === false) return
|
||||
this.popoverRef.setShow(false)
|
||||
onUpdateShow(false)
|
||||
})
|
||||
},
|
||||
onNegativeClick: () => {
|
||||
const {
|
||||
onNegativeClick = () => true,
|
||||
'onUpdate:show': onUpdateShow
|
||||
} = this
|
||||
Promise.resolve(onNegativeClick()).then((value) => {
|
||||
if (value === false) return
|
||||
this.popoverRef.setShow(false)
|
||||
onUpdateShow(false)
|
||||
})
|
||||
}
|
||||
},
|
||||
{
|
||||
action: slots.action,
|
||||
icon: slots.icon,
|
||||
default: slots.default
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
114
src/popconfirm/src/Popconfirm.ts
Normal file
114
src/popconfirm/src/Popconfirm.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import { h, ref, defineComponent, provide, PropType, reactive } from 'vue'
|
||||
import {
|
||||
NPopover,
|
||||
popoverProps,
|
||||
PopoverRef,
|
||||
PopoverTrigger
|
||||
} from '../../popover'
|
||||
import { omit, keep, call } from '../../_utils'
|
||||
import { useTheme } from '../../_mixins'
|
||||
import type { ThemeProps } from '../../_mixins'
|
||||
import { popconfirmLight } from '../styles'
|
||||
import type { PopconfirmTheme } from '../styles'
|
||||
import PopconfirmPanel, { panelPropKeys } from './PopconfirmPanel'
|
||||
import style from './styles/index.cssr'
|
||||
import type { PopconfirmInjection } from './interface'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Popconfirm',
|
||||
props: {
|
||||
...(useTheme.props as ThemeProps<PopconfirmTheme>),
|
||||
...popoverProps,
|
||||
positiveText: String,
|
||||
negativeText: String,
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
trigger: {
|
||||
type: String as PropType<PopoverTrigger>,
|
||||
default: 'click'
|
||||
},
|
||||
onPositiveClick: Function as PropType<
|
||||
(e: MouseEvent) => Promise<boolean> | boolean | any
|
||||
>,
|
||||
onNegativeClick: Function as PropType<
|
||||
(e: MouseEvent) => Promise<boolean> | boolean | any
|
||||
>
|
||||
},
|
||||
setup (props) {
|
||||
const themeRef = useTheme(
|
||||
'Popconfirm',
|
||||
'Popconfirm',
|
||||
style,
|
||||
popconfirmLight,
|
||||
props
|
||||
)
|
||||
const popoverInstRef = ref<PopoverRef | null>(null)
|
||||
function handlePositiveClick (e: MouseEvent): void {
|
||||
const { onPositiveClick, 'onUpdate:show': onUpdateShow } = props
|
||||
void Promise.resolve(onPositiveClick ? onPositiveClick(e) : true).then(
|
||||
(value) => {
|
||||
if (value === false) return
|
||||
popoverInstRef.value?.setShow(false)
|
||||
if (onUpdateShow) call(onUpdateShow, false)
|
||||
}
|
||||
)
|
||||
}
|
||||
function handleNegativeClick (e: MouseEvent): void {
|
||||
const { onNegativeClick, 'onUpdate:show': onUpdateShow } = props
|
||||
void Promise.resolve(onNegativeClick ? onNegativeClick(e) : true).then(
|
||||
(value) => {
|
||||
if (value === false) return
|
||||
popoverInstRef.value?.setShow(false)
|
||||
if (onUpdateShow) call(onUpdateShow, false)
|
||||
}
|
||||
)
|
||||
}
|
||||
provide<PopconfirmInjection>(
|
||||
'NPopconfirm',
|
||||
reactive({
|
||||
mergedTheme: themeRef
|
||||
})
|
||||
)
|
||||
return {
|
||||
mergedTheme: themeRef,
|
||||
popoverInstRef,
|
||||
handlePositiveClick,
|
||||
handleNegativeClick
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { $slots: slots, $props: props, mergedTheme } = this
|
||||
return h(
|
||||
NPopover,
|
||||
{
|
||||
...omit(props, panelPropKeys, {
|
||||
unstableTheme: mergedTheme.peers.Popover,
|
||||
unstableThemeOverrides: mergedTheme.overrides.Popover
|
||||
}),
|
||||
class: 'n-popconfirm',
|
||||
ref: 'popoverInstRef'
|
||||
},
|
||||
{
|
||||
trigger: slots.activator || slots.trigger,
|
||||
default: () => {
|
||||
const panelProps = keep(props, panelPropKeys)
|
||||
return h(
|
||||
PopconfirmPanel,
|
||||
{
|
||||
...panelProps,
|
||||
onPositiveClick: this.handlePositiveClick,
|
||||
onNegativeClick: this.handleNegativeClick
|
||||
},
|
||||
{
|
||||
action: slots.action,
|
||||
icon: slots.icon,
|
||||
default: slots.default
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
109
src/popconfirm/src/PopconfirmPanel.tsx
Normal file
109
src/popconfirm/src/PopconfirmPanel.tsx
Normal file
@ -0,0 +1,109 @@
|
||||
import {
|
||||
h,
|
||||
defineComponent,
|
||||
computed,
|
||||
inject,
|
||||
PropType,
|
||||
renderSlot,
|
||||
VNode,
|
||||
CSSProperties
|
||||
} from 'vue'
|
||||
import { NButton } from '../../button'
|
||||
import { NBaseIcon } from '../../_base'
|
||||
import { WarningIcon } from '../../_base/icons'
|
||||
import { useLocale } from '../../_mixins'
|
||||
import { keysOf } from '../../_utils'
|
||||
import type { PopconfirmInjection } from './interface'
|
||||
|
||||
export const panelProps = {
|
||||
positiveText: String,
|
||||
negativeText: String,
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
onPositiveClick: {
|
||||
type: Function as PropType<(e: MouseEvent) => void>,
|
||||
required: true
|
||||
},
|
||||
onNegativeClick: {
|
||||
type: Function as PropType<(e: MouseEvent) => void>,
|
||||
required: true
|
||||
}
|
||||
} as const
|
||||
|
||||
export const panelPropKeys = keysOf(panelProps)
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NPopconfirmPanel',
|
||||
props: panelProps,
|
||||
setup (props) {
|
||||
const { locale: localeRef } = useLocale('Popconfirm')
|
||||
const NPopconfirm = inject<PopconfirmInjection>(
|
||||
'NPopconfirm'
|
||||
) as PopconfirmInjection
|
||||
return {
|
||||
...useLocale('Popconfirm'),
|
||||
cssVars: computed(() => {
|
||||
const {
|
||||
common: { cubicBezierEaseInOut },
|
||||
self: { fontSize, iconSize, iconColor }
|
||||
} = NPopconfirm.mergedTheme
|
||||
return {
|
||||
'--bezier': cubicBezierEaseInOut,
|
||||
'--font-size': fontSize,
|
||||
'--icon-size': iconSize,
|
||||
'--icon-color': iconColor
|
||||
}
|
||||
}),
|
||||
localizedPositiveText: computed(() => {
|
||||
return props.positiveText || localeRef.value.positiveText
|
||||
}),
|
||||
localizedNegativeText: computed(() => {
|
||||
return props.negativeText || localeRef.value.negativeText
|
||||
}),
|
||||
handlePositiveClick (e: MouseEvent) {
|
||||
props.onPositiveClick(e)
|
||||
},
|
||||
handleNegativeClick (e: MouseEvent) {
|
||||
props.onNegativeClick(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
render () {
|
||||
return (
|
||||
<div style={this.cssVars as CSSProperties}>
|
||||
<div class="n-popconfirm__body">
|
||||
{this.showIcon ? (
|
||||
<div class="n-popconfirm__icon">
|
||||
<slot name="icon">
|
||||
<NBaseIcon>{{ default: () => <WarningIcon /> }}</NBaseIcon>
|
||||
</slot>
|
||||
</div>
|
||||
) : null}
|
||||
{renderSlot(this.$slots, 'default')}
|
||||
</div>
|
||||
<div class="n-popconfirm__action">
|
||||
{renderSlot(
|
||||
this.$slots,
|
||||
'action',
|
||||
undefined,
|
||||
() =>
|
||||
[
|
||||
<NButton size="small" onClick={this.handleNegativeClick}>
|
||||
{this.localizedNegativeText}
|
||||
</NButton>,
|
||||
<NButton
|
||||
size="small"
|
||||
type="primary"
|
||||
onClick={this.handlePositiveClick}
|
||||
>
|
||||
{this.localizedPositiveText}
|
||||
</NButton>
|
||||
] as VNode[]
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
@ -1,94 +0,0 @@
|
||||
<template>
|
||||
<div :style="cssVars">
|
||||
<div class="n-popconfirm__body">
|
||||
<div v-if="showIcon" class="n-popconfirm__icon">
|
||||
<slot name="icon">
|
||||
<n-base-icon>
|
||||
<warning-icon />
|
||||
</n-base-icon>
|
||||
</slot>
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
<div class="n-popconfirm__action">
|
||||
<slot name="action">
|
||||
<n-button size="small" @click="handleNegativeClick">
|
||||
{{ localizedNegativeText }}
|
||||
</n-button>
|
||||
<n-button size="small" type="primary" @click="handlePositiveClick">
|
||||
{{ localizedPositiveText }}
|
||||
</n-button>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed, inject } from 'vue'
|
||||
import { NButton } from '../../button'
|
||||
import { NBaseIcon } from '../../_base'
|
||||
import { WarningIcon } from '../../_base/icons'
|
||||
import { useLocale } from '../../_mixins'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NPopconfirmPanel',
|
||||
components: {
|
||||
NButton,
|
||||
NBaseIcon,
|
||||
WarningIcon
|
||||
},
|
||||
props: {
|
||||
positiveText: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
negativeText: {
|
||||
type: String,
|
||||
default: undefined
|
||||
},
|
||||
showIcon: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
onPositiveClick: {
|
||||
type: Function,
|
||||
required: true
|
||||
},
|
||||
onNegativeClick: {
|
||||
type: Function,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const { locale: localeRef } = useLocale('Popconfirm')
|
||||
const NPopconfirm = inject('NPopconfirm')
|
||||
return {
|
||||
...useLocale('Popconfirm'),
|
||||
localizedPositiveText: computed(() => {
|
||||
return props.positiveText || localeRef.value.positiveText
|
||||
}),
|
||||
localizedNegativeText: computed(() => {
|
||||
return props.negativeText || localeRef.value.negativeText
|
||||
}),
|
||||
handlePositiveClick () {
|
||||
props.onPositiveClick()
|
||||
},
|
||||
handleNegativeClick () {
|
||||
props.onNegativeClick()
|
||||
},
|
||||
cssVars: computed(() => {
|
||||
const {
|
||||
common: { cubicBezierEaseInOut },
|
||||
self: { fontSize, iconSize, iconColor }
|
||||
} = NPopconfirm.mergedTheme
|
||||
return {
|
||||
'--bezier': cubicBezierEaseInOut,
|
||||
'--font-size': fontSize,
|
||||
'--icon-size': iconSize,
|
||||
'--icon-color': iconColor
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
6
src/popconfirm/src/interface.ts
Normal file
6
src/popconfirm/src/interface.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import type { MergedTheme } from '../../_mixins'
|
||||
import type { PopconfirmTheme } from '../styles'
|
||||
|
||||
export interface PopconfirmInjection {
|
||||
mergedTheme: MergedTheme<PopconfirmTheme>
|
||||
}
|
@ -22,7 +22,7 @@ export default cB('popconfirm', [
|
||||
`)
|
||||
]),
|
||||
cE('action', `
|
||||
margin-top: 14px;
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
`, [
|
@ -2,8 +2,9 @@ import { buttonDark } from '../../button/styles'
|
||||
import { popoverDark } from '../../popover/styles'
|
||||
import { commonDark } from '../../_styles/new-common'
|
||||
import commonVars from './_common'
|
||||
import type { PopconfirmTheme } from './light'
|
||||
|
||||
export default {
|
||||
const popconfirmDark: PopconfirmTheme = {
|
||||
name: 'Popconfirm',
|
||||
common: commonDark,
|
||||
peers: {
|
||||
@ -19,3 +20,5 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default popconfirmDark
|
@ -1,2 +0,0 @@
|
||||
export { default as popconfirmDark } from './dark.js'
|
||||
export { default as popconfirmLight } from './light.js'
|
3
src/popconfirm/styles/index.ts
Normal file
3
src/popconfirm/styles/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as popconfirmDark } from './dark'
|
||||
export { default as popconfirmLight } from './light'
|
||||
export type { PopconfirmThemeVars, PopconfirmTheme } from './light'
|
@ -1,21 +0,0 @@
|
||||
import { buttonLight } from '../../button/styles'
|
||||
import { popoverLight } from '../../popover/styles'
|
||||
import { commonLight } from '../../_styles/new-common'
|
||||
import commonVars from './_common'
|
||||
|
||||
export default {
|
||||
name: 'Popconfirm',
|
||||
common: commonLight,
|
||||
peers: {
|
||||
Button: buttonLight,
|
||||
Popover: popoverLight
|
||||
},
|
||||
self (vars) {
|
||||
const { fontSize, warningColor } = vars
|
||||
return {
|
||||
...commonVars,
|
||||
fontSize,
|
||||
iconColor: warningColor
|
||||
}
|
||||
}
|
||||
}
|
30
src/popconfirm/styles/light.ts
Normal file
30
src/popconfirm/styles/light.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { buttonLight } from '../../button/styles'
|
||||
import { popoverLight } from '../../popover/styles'
|
||||
import { createTheme } from '../../_mixins'
|
||||
import { commonLight, ThemeCommonVars } from '../../_styles/new-common'
|
||||
|
||||
import commonVars from './_common'
|
||||
|
||||
const self = (vars: ThemeCommonVars) => {
|
||||
const { fontSize, warningColor } = vars
|
||||
return {
|
||||
...commonVars,
|
||||
fontSize,
|
||||
iconColor: warningColor
|
||||
}
|
||||
}
|
||||
|
||||
export type PopconfirmThemeVars = ReturnType<typeof self>
|
||||
|
||||
const popconfirmLight = createTheme({
|
||||
name: 'Popconfirm',
|
||||
common: commonLight,
|
||||
peers: {
|
||||
Button: buttonLight,
|
||||
Popover: popoverLight
|
||||
},
|
||||
self
|
||||
})
|
||||
|
||||
export default popconfirmLight
|
||||
export type PopconfirmTheme = typeof popconfirmLight
|
@ -1,2 +1,2 @@
|
||||
export { default as NPopover, popoverProps } from './src/Popover'
|
||||
export type { PopoverRef } from './src/Popover'
|
||||
export type { PopoverTrigger, PopoverRef } from './src/interface'
|
||||
|
@ -13,10 +13,12 @@ import {
|
||||
import { VBinder, VTarget, FollowerPlacement } from 'vueuc'
|
||||
import { useMergedState, useCompitable, useIsMounted, useMemo } from 'vooks'
|
||||
import { call, keep, warn } from '../../_utils'
|
||||
import type { MaybeArray } from '../../_utils'
|
||||
import { useTheme } from '../../_mixins'
|
||||
import type { ThemeProps } from '../../_mixins'
|
||||
import NPopoverBody, { popoverBodyProps } from './PopoverBody'
|
||||
import type { PopoverTheme } from '../styles'
|
||||
import { PopoverTrigger } from './interface'
|
||||
|
||||
const bodyPropKeys = Object.keys(popoverBodyProps) as Array<
|
||||
keyof typeof popoverBodyProps
|
||||
@ -67,10 +69,6 @@ interface BodyInstance {
|
||||
[key: string]: unknown
|
||||
}
|
||||
|
||||
export interface PopoverRef {
|
||||
syncPosition: () => void
|
||||
}
|
||||
|
||||
export interface PopoverInjection {
|
||||
handleMouseLeave: (e: MouseEvent) => void
|
||||
handleMouseEnter: (e: MouseEvent) => void
|
||||
@ -82,7 +80,6 @@ export interface PopoverInjection {
|
||||
}
|
||||
|
||||
export const popoverProps = {
|
||||
...(useTheme.props as ThemeProps<PopoverTheme>),
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: undefined
|
||||
@ -96,7 +93,7 @@ export const popoverProps = {
|
||||
default: true
|
||||
},
|
||||
trigger: {
|
||||
type: String as PropType<'hover' | 'click'>,
|
||||
type: String as PropType<PopoverTrigger>,
|
||||
default: undefined
|
||||
},
|
||||
delay: {
|
||||
@ -154,13 +151,14 @@ export const popoverProps = {
|
||||
},
|
||||
// events
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:show': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
'onUpdate:show': Function as PropType<
|
||||
MaybeArray<(value: boolean) => void> | undefined
|
||||
>,
|
||||
// deprecated
|
||||
onShow: {
|
||||
type: Function,
|
||||
type: Function as PropType<
|
||||
MaybeArray<(value: boolean) => void> | undefined
|
||||
>,
|
||||
validator: (): boolean => {
|
||||
warn(
|
||||
'popover',
|
||||
@ -171,7 +169,9 @@ export const popoverProps = {
|
||||
default: undefined
|
||||
},
|
||||
onHide: {
|
||||
type: Function,
|
||||
type: Function as PropType<
|
||||
MaybeArray<(value: boolean) => void> | undefined
|
||||
>,
|
||||
validator: (): boolean => {
|
||||
warn(
|
||||
'popover',
|
||||
@ -202,7 +202,10 @@ export const popoverProps = {
|
||||
export default defineComponent({
|
||||
name: 'Popover',
|
||||
inheritAttrs: false,
|
||||
props: popoverProps,
|
||||
props: {
|
||||
...(useTheme.props as ThemeProps<PopoverTheme>),
|
||||
...popoverProps
|
||||
},
|
||||
setup (props) {
|
||||
const isMountedRef = useIsMounted()
|
||||
// setup show
|
||||
|
6
src/popover/src/interface.ts
Normal file
6
src/popover/src/interface.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export type PopoverTrigger = 'click' | 'hover'
|
||||
|
||||
export interface PopoverRef {
|
||||
syncPosition: () => void
|
||||
setShow: (value: boolean) => void
|
||||
}
|
Loading…
Reference in New Issue
Block a user