Files
dopamine 0ca1570aa1 chore: upgrade to Vue 3.5 (#22096)
* chore: upgrade deps

* chore: replace __ExtractPublicPropTypes with ExtractPublicPropTypes

* fix: get rid of type errors

* fix: resolve test errors with @vue/test-utils v2.4.6

* fix: resolve test errors with Vue 3.5.22

* ci: set pnpm flag

* chore: update the Vue peer dependency version

* Apply suggestion from @tolking

Co-authored-by: qiang <qw13131wang@gmail.com>

* docs: update example code

Co-authored-by: warmthsea <2586244885@qq.com>

* chore: remove csstype (#22487)

* chore: fix merge code type error

* chore: fix test:ssr error

- Cannot read properties of undefined (reading 'getSSRProps')

* chore: fix typecheck:vitest error

* chore: update pnpm yaml file

* test: fix collapse accordion error

* chore: update deps

* chore: fix type error

* chore: lock file

* chore: sync change

sync with the remove of vue macro

* refactor: use computed instead of eagerComputed

* fix: timeline.test.tsx typecheck

* chore: clean lock file

try dont throw CodeFactor issues in ci

did:
- rm pnpm-lock.yaml
- rm -rf ./**/node_modules
- pnpm store prune
- pnpm cache delete
- pnpm install

Also stay in 3.1.0 for vue-tsc in order to avoid the warnings of
template refs, see https://github.com/vuejs/language-tools/issues/5815

* chore: format code

---------

Co-authored-by: Dsaquel <291874700n@gmail.com>
Co-authored-by: qiang <qw13131wang@gmail.com>
Co-authored-by: warmthsea <2586244885@qq.com>
Co-authored-by: Noblet Ouways <91417411+Dsaquel@users.noreply.github.com>
Co-authored-by: sea <45450994+warmthsea@users.noreply.github.com>
Co-authored-by: btea <2356281422@qq.com>
2025-12-16 09:34:03 +08:00

212 lines
4.9 KiB
TypeScript

import { computed, getCurrentInstance, onMounted, watch } from 'vue'
import {
buildProp,
definePropType,
isBoolean,
isClient,
isFunction,
} from '@element-plus/utils'
import type { ExtractPropType } from '@element-plus/utils'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import type {
ComponentPublicInstance,
ExtractPropTypes,
ExtractPublicPropTypes,
Ref,
} from 'vue'
const _prop = buildProp({
type: definePropType<boolean | null>(Boolean),
default: null,
} as const)
const _event = buildProp({
type: definePropType<(val: boolean) => void>(Function),
} as const)
export type UseModelTogglePropsRaw<T extends string> = {
[K in T]: typeof _prop
} & {
[K in `onUpdate:${T}`]: typeof _event
}
export type UseModelTogglePropsGeneric<T extends string> = {
[K in T]: ExtractPropType<typeof _prop>
} & {
[K in `onUpdate:${T}`]: ExtractPropType<typeof _event>
}
export const createModelToggleComposable = <T extends string>(name: T) => {
const updateEventKey = `update:${name}` as const
const updateEventKeyRaw = `onUpdate:${name}` as const
const useModelToggleEmits = [updateEventKey]
const useModelToggleProps = {
[name]: _prop,
[updateEventKeyRaw]: _event,
} as UseModelTogglePropsRaw<T>
const useModelToggle = ({
indicator,
toggleReason,
shouldHideWhenRouteChanges,
shouldProceed,
onShow,
onHide,
}: ModelToggleParams) => {
const instance = getCurrentInstance()!
const { emit } = instance
const props = instance.props as UseModelTogglePropsGeneric<T> & {
disabled: boolean
}
const hasUpdateHandler = computed(() =>
isFunction(props[updateEventKeyRaw])
)
// when it matches the default value we say this is absent
// though this could be mistakenly passed from the user but we need to rule out that
// condition
const isModelBindingAbsent = computed(() => props[name] === null)
const doShow = (event?: Event) => {
if (indicator.value === true) {
return
}
indicator.value = true
if (toggleReason) {
toggleReason.value = event
}
if (isFunction(onShow)) {
onShow(event)
}
}
const doHide = (event?: Event) => {
if (indicator.value === false) {
return
}
indicator.value = false
if (toggleReason) {
toggleReason.value = event
}
if (isFunction(onHide)) {
onHide(event)
}
}
const show = (event?: Event) => {
if (
props.disabled === true ||
(isFunction(shouldProceed) && !shouldProceed())
)
return
const shouldEmit = hasUpdateHandler.value && isClient
if (shouldEmit) {
emit(updateEventKey, true)
}
if (isModelBindingAbsent.value || !shouldEmit) {
doShow(event)
}
}
const hide = (event?: Event) => {
if (props.disabled === true || !isClient) return
const shouldEmit = hasUpdateHandler.value && isClient
if (shouldEmit) {
emit(updateEventKey, false)
}
if (isModelBindingAbsent.value || !shouldEmit) {
doHide(event)
}
}
const onChange = (val: boolean) => {
if (!isBoolean(val)) return
if (props.disabled && val) {
if (hasUpdateHandler.value) {
emit(updateEventKey, false)
}
} else if (indicator.value !== val) {
if (val) {
doShow()
} else {
doHide()
}
}
}
const toggle = () => {
if (indicator.value) {
hide()
} else {
show()
}
}
watch(() => props[name], onChange)
if (
shouldHideWhenRouteChanges &&
instance.appContext.config.globalProperties.$route !== undefined
) {
watch(
() => ({
...(
instance.proxy as ComponentPublicInstance<{
$route: RouteLocationNormalizedLoaded
}>
).$route,
}),
() => {
if (shouldHideWhenRouteChanges.value && indicator.value) {
hide()
}
}
)
}
onMounted(() => {
onChange(props[name])
})
return {
hide,
show,
toggle,
hasUpdateHandler,
}
}
return {
useModelToggle,
useModelToggleProps,
useModelToggleEmits,
}
}
const { useModelToggle, useModelToggleProps, useModelToggleEmits } =
createModelToggleComposable('modelValue')
export { useModelToggle, useModelToggleEmits, useModelToggleProps }
export type UseModelToggleProps = ExtractPropTypes<typeof useModelToggleProps>
export type UseModelTogglePropsPublic = ExtractPublicPropTypes<
typeof useModelToggleProps
>
export type ModelToggleParams = {
indicator: Ref<boolean>
toggleReason?: Ref<Event | undefined>
shouldHideWhenRouteChanges?: Ref<boolean>
shouldProceed?: () => boolean
onShow?: (event?: Event) => void
onHide?: (event?: Event) => void
}