refactor(hooks): refactor hooks (#4253)

* refactor(hooks): remove use-css-var

* refactor(hooks): remove use-events

* refactor(hooks): remove use-migrating

* refactor(hooks): remove use-transition

* refactor(hooks): named export useAttrs

* refactor(hooks): named export useFocus

* refactor(hooks): refactor useFormItem

* refactor(hooks): refactor useGlobalConfig

* refactor(hooks): refactor useLocale

* refactor(hooks): refactor useLockscreen

* refactor(hooks): refactor useModal

* refactor(hooks): refactor useModelToggle

* refactor(hooks): refactor usePreventGlobal

* refactor(hooks): refactor useRestoreActive

* refactor(hooks): refactor useTeleport

* refactor(hooks): refactor useThrottleRender

* refactor(hooks): refactor useTimeout

* refactor(hooks): refactor useTransitionFallthrogh
This commit is contained in:
三咲智子
2021-11-29 15:58:44 +08:00
committed by GitHub
parent 17d6287d6c
commit bbd16a08e9
69 changed files with 233 additions and 628 deletions

View File

@@ -40,7 +40,7 @@
import { computed, defineComponent, ref } from 'vue'
import dayjs from 'dayjs'
import localeData from 'dayjs/plugin/localeData'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { rangeArr } from '@element-plus/components/time-picker'
import type { Dayjs } from 'dayjs'
import type { PropType } from 'vue'
@@ -73,7 +73,7 @@ export default defineComponent({
},
emits: ['pick'],
setup(props, ctx) {
const { lang } = useLocaleInject()
const { lang } = useLocale()
const WEEK_DAYS = ref(
dayjs().locale(lang.value).localeData().weekdaysShort()
)

View File

@@ -51,7 +51,7 @@ import { ref, computed, defineComponent } from 'vue'
import dayjs from 'dayjs'
import ElButton from '@element-plus/components/button'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { debugWarn } from '@element-plus/utils/error'
import DateTable from './date-table.vue'
import type { PropType, ComputedRef } from 'vue'
@@ -94,7 +94,7 @@ export default defineComponent({
emits: ['input', 'update:modelValue'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
const selectedDay = ref(null)
const now = dayjs().locale(lang.value)

View File

@@ -30,7 +30,7 @@
<script lang="ts">
import { computed, defineComponent, getCurrentInstance, inject, ref } from 'vue'
import ElScrollbar from '@element-plus/components/scrollbar'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { generateId } from '@element-plus/utils/util'
import ElCascaderNode from './node.vue'
import { CASCADER_PANEL_INJECTION_KEY } from './types'
@@ -60,7 +60,7 @@ export default defineComponent({
setup(props) {
const instance = getCurrentInstance()!
const { t } = useLocaleInject()
const { t } = useLocale()
const id = generateId()
let activeNode: Nullable<HTMLElement> = null
let hoverTimer: Nullable<TimeoutHandle> = null

View File

@@ -169,7 +169,7 @@ import ElIcon from '@element-plus/components/icon'
import { elFormKey, elFormItemKey } from '@element-plus/tokens'
import { ClickOutside as Clickoutside } from '@element-plus/directives'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { EVENT_CODE, focusNode, getSibling } from '@element-plus/utils/aria'
import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from '@element-plus/utils/constants'
@@ -301,7 +301,7 @@ export default defineComponent({
let inputInitialHeight = 0
let pressDeleteCount = 0
const { t } = useLocaleInject()
const { t } = useLocale()
const $ELEMENT = useGlobalConfig()
const elForm = inject(elFormKey, {} as ElFormContext)
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)

View File

@@ -111,7 +111,7 @@ import ElButton from '@element-plus/components/button'
import ElIcon from '@element-plus/components/icon'
import { ClickOutside } from '@element-plus/directives'
import { elFormItemKey, elFormKey } from '@element-plus/tokens'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ElPopper, { Effect } from '@element-plus/components/popper'
import ElInput from '@element-plus/components/input'
import { UPDATE_MODEL_EVENT } from '@element-plus/utils/constants'
@@ -162,7 +162,7 @@ export default defineComponent({
emits: ['change', 'active-change', UPDATE_MODEL_EVENT],
setup(props, { emit }) {
const ELEMENT = useGlobalConfig()
const { t } = useLocaleInject()
const { t } = useLocale()
const elForm = inject(elFormKey, {} as ElFormContext)
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)

View File

@@ -1,6 +1,6 @@
import { h, ref, inject, reactive, nextTick } from 'vue'
import { mount } from '@vue/test-utils'
import { LocaleInjectionKey } from '@element-plus/hooks'
import { localeContextKey } from '@element-plus/hooks'
import Chinese from '@element-plus/locale/lang/zh-cn'
import English from '@element-plus/locale/lang/en'
import { ElButton } from '@element-plus/components'
@@ -9,7 +9,7 @@ import type { Language } from '@element-plus/locale'
const TestComp = {
setup() {
const { t } = inject(LocaleInjectionKey)
const { t } = inject(localeContextKey)
return () => {
return h('div', t('el.popconfirm.confirmButtonText'))
}

View File

@@ -1,5 +1,5 @@
import { provide, defineComponent } from 'vue'
import { useLocale } from '@element-plus/hooks'
import { provideLocale } from '@element-plus/hooks'
import { configProviderContextKey } from '@element-plus/tokens'
import { configProviderProps } from './config-provider'
@@ -7,7 +7,7 @@ export const ConfigProvider = defineComponent({
name: 'ElConfigProvider',
props: configProviderProps,
setup(props, { slots }) {
useLocale()
provideLocale()
provide(configProviderContextKey, props)
return () => slots.default?.()
},

View File

@@ -35,7 +35,7 @@
<script lang="ts">
import { defineComponent, computed, ref } from 'vue'
import dayjs from 'dayjs'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { coerceTruthyValueToArray } from '@element-plus/utils/util'
import ElDatePickerCell from './basic-cell-render'
import type { PropType } from 'vue'
@@ -85,7 +85,7 @@ export default defineComponent({
emits: ['changerange', 'pick', 'select'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
// data
const lastRow = ref(null)
const lastColumn = ref(null)

View File

@@ -21,7 +21,7 @@
<script lang="ts">
import { defineComponent, computed, ref } from 'vue'
import dayjs from 'dayjs'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { rangeArr } from '@element-plus/components/time-picker'
import { hasClass } from '@element-plus/utils/dom'
import { coerceTruthyValueToArray } from '@element-plus/utils/util'
@@ -68,7 +68,7 @@ export default defineComponent({
emits: ['changerange', 'pick', 'select'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
const months = ref(
props.date
.locale('en')

View File

@@ -46,7 +46,7 @@
<script lang="ts">
import { defineComponent, computed } from 'vue'
import dayjs from 'dayjs'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { rangeArr } from '@element-plus/components/time-picker'
import { hasClass } from '@element-plus/utils/dom'
import { coerceTruthyValueToArray } from '@element-plus/utils/util'
@@ -77,7 +77,7 @@ export default defineComponent({
emits: ['pick'],
setup(props, ctx) {
const { lang } = useLocaleInject()
const { lang } = useLocale()
const startYear = computed(() => {
return Math.floor(props.date.year() / 10) * 10
})

View File

@@ -166,7 +166,7 @@ import { computed, defineComponent, inject, ref, watch } from 'vue'
import dayjs from 'dayjs'
import ElButton from '@element-plus/components/button'
import { ClickOutside } from '@element-plus/directives'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ElInput from '@element-plus/components/input'
import {
extractDateFormat,
@@ -230,7 +230,7 @@ export default defineComponent({
},
emits: ['pick', 'set-picker-option'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
const pickerBase = inject('EP_PICKER_BASE') as any
const {

View File

@@ -237,7 +237,7 @@ import { computed, defineComponent, inject, ref, watch } from 'vue'
import dayjs from 'dayjs'
import ElButton from '@element-plus/components/button'
import { ClickOutside } from '@element-plus/directives'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ElInput from '@element-plus/components/input'
import {
extractDateFormat,
@@ -288,7 +288,7 @@ export default defineComponent({
emits: ['pick', 'set-picker-option', 'calendar-change'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
const leftDate = ref(dayjs().locale(lang.value))
const rightDate = ref(dayjs().locale(lang.value).add(1, 'month'))
const minDate = ref(null)

View File

@@ -100,7 +100,7 @@
import { defineComponent, computed, ref, watch, inject } from 'vue'
import dayjs from 'dayjs'
import ElIcon from '@element-plus/components/icon'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { DArrowLeft, DArrowRight } from '@element-plus/icons'
import MonthTable from './basic-month-table.vue'
@@ -120,7 +120,7 @@ export default defineComponent({
emits: ['pick', 'set-picker-option'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
const leftDate = ref(dayjs().locale(lang.value))
const rightDate = ref(dayjs().locale(lang.value).add(1, 'year'))

View File

@@ -1,7 +1,7 @@
import { computed, ref, watch, nextTick, onMounted } from 'vue'
import { useTimeoutFn } from '@vueuse/core'
import { useLockScreen, useRestoreActive, useModal } from '@element-plus/hooks'
import { useLockscreen, useRestoreActive, useModal } from '@element-plus/hooks'
import { UPDATE_MODEL_EVENT } from '@element-plus/utils/constants'
import isServer from '@element-plus/utils/isServer'
import PopupManager from '@element-plus/utils/popup-manager'
@@ -116,7 +116,7 @@ export const useDialog = (
}
if (props.lockScroll) {
useLockScreen(visible)
useLockscreen(visible)
}
if (props.closeOnPressEscape) {

View File

@@ -18,7 +18,7 @@
<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ImgEmpty from './img-empty.vue'
import { emptyProps } from './empty'
@@ -33,7 +33,7 @@ export default defineComponent({
props: emptyProps,
setup(props) {
const { t } = useLocaleInject()
const { t } = useLocale()
const emptyDescription = computed(
() => props.description || t('el.table.emptyText')
)

View File

@@ -88,7 +88,7 @@ import {
} from 'vue'
import { useEventListener } from '@vueuse/core'
import ElIcon from '@element-plus/components/icon'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { EVENT_CODE } from '@element-plus/utils/aria'
import { rafThrottle, isFirefox } from '@element-plus/utils/util'
import {
@@ -140,7 +140,7 @@ export default defineComponent({
emits: imageViewerEmits,
setup(props, { emit }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const wrapper = ref<HTMLDivElement>()
const img = ref<HTMLImageElement>()

View File

@@ -45,7 +45,7 @@
import { defineComponent, computed, ref, onMounted, watch, nextTick } from 'vue'
import { isString } from '@vue/shared'
import { useEventListener, useThrottleFn } from '@vueuse/core'
import { useAttrs, useLocaleInject } from '@element-plus/hooks'
import { useAttrs, useLocale } from '@element-plus/hooks'
import ImageViewer from '@element-plus/components/image-viewer'
import isServer from '@element-plus/utils/isServer'
import { getScrollContainer, isInContainer } from '@element-plus/utils/dom'
@@ -69,7 +69,7 @@ export default defineComponent({
emits: imageEmits,
setup(props, { emit, attrs: rawAttrs }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const attrs = useAttrs()
const hasLoadError = ref(false)

View File

@@ -131,8 +131,8 @@ import ElButton from '@element-plus/components/button'
import { TrapFocus } from '@element-plus/directives'
import {
useModal,
useLockScreen,
useLocaleInject,
useLockscreen,
useLocale,
useRestoreActive,
usePreventGlobal,
} from '@element-plus/hooks'
@@ -212,7 +212,7 @@ export default defineComponent({
emits: ['vanish', 'action'],
setup(props, { emit }) {
// const popup = usePopup(props, doClose)
const { t } = useLocaleInject()
const { t } = useLocale()
const visible = ref(false)
// s represents state
const state = reactive<MessageBoxState>({
@@ -414,7 +414,7 @@ export default defineComponent({
// locks the screen to prevent scroll
if (props.lockScroll) {
useLockScreen(visible)
useLockscreen(visible)
}
// restore to prev active element.

View File

@@ -19,7 +19,7 @@
import { defineComponent } from 'vue'
import { ElIcon } from '@element-plus/components/icon'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { pageHeaderEmits, pageHeaderProps } from './page-header'
export default defineComponent({
@@ -33,7 +33,7 @@ export default defineComponent({
emits: pageHeaderEmits,
setup(_, { emit }) {
const { t } = useLocaleInject()
const { t } = useLocale()
function handleClick() {
emit('back')

View File

@@ -18,7 +18,7 @@
<script lang="ts">
import { computed, defineComponent, ref } from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ElInput from '@element-plus/components/input'
import { usePagination } from '../usePagination'
@@ -29,7 +29,7 @@ export default defineComponent({
},
setup() {
const { t } = useLocaleInject()
const { t } = useLocale()
const { pageCount, disabled, currentPage, changeEvent } = usePagination()
const userInput = ref<number>()
const innerValue = computed(() => userInput.value ?? currentPage?.value)

View File

@@ -21,7 +21,7 @@
import { defineComponent, watch, computed, ref } from 'vue'
import isEqual from 'lodash/isEqual'
import { ElSelect, ElOption } from '@element-plus/components/select'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { buildProps, definePropType, mutable } from '@element-plus/utils/props'
import { usePagination } from '../usePagination'
@@ -55,7 +55,7 @@ export default defineComponent({
emits: ['page-size-change'],
setup(props, { emit }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const pagination = usePagination()
const innerPageSize = ref<Nullable<number>>(props.pageSize)

View File

@@ -10,7 +10,7 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import type { ExtractPropTypes } from 'vue'
@@ -28,7 +28,7 @@ export default defineComponent({
props: paginationTotalProps,
setup() {
const { t } = useLocaleInject()
const { t } = useLocale()
return {
t,
}

View File

@@ -7,7 +7,7 @@ import {
getCurrentInstance,
watch,
} from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { debugWarn } from '@element-plus/utils/error'
import { buildProps, definePropType, mutable } from '@element-plus/utils/props'
import { elPaginationKey } from '@element-plus/tokens'
@@ -105,7 +105,7 @@ export default defineComponent({
emits: paginationEmits,
setup(props, { emit, slots }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const vnodeProps = getCurrentInstance()!.vnode.props || {}
// we can find @xxx="xxx" props on `vnodeProps` to check if user bind corresponding events
const hasCurrentPageListener =

View File

@@ -38,7 +38,7 @@ import { defineComponent, ref, computed } from 'vue'
import ElButton from '@element-plus/components/button'
import ElIcon from '@element-plus/components/icon'
import ElPopper, { Effect } from '@element-plus/components/popper'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { popconfirmProps, popconfirmEmits } from './popconfirm'
export default defineComponent({
@@ -54,7 +54,7 @@ export default defineComponent({
emits: popconfirmEmits,
setup(props, { emit }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const visible = ref(false)
const confirm = () => {
visible.value = false

View File

@@ -12,7 +12,7 @@ import { isArray, isFunction, isObject } from '@vue/shared'
import isEqual from 'lodash/isEqual'
import lodashDebounce from 'lodash/debounce'
import { elFormKey, elFormItemKey } from '@element-plus/tokens'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from '@element-plus/utils/constants'
import {
addResizeListener,
@@ -41,7 +41,7 @@ const TAG_BASE_WIDTH = {
const useSelect = (props: ExtractPropTypes<typeof SelectProps>, emit) => {
// inject
const { t } = useLocaleInject()
const { t } = useLocale()
const elForm = inject(elFormKey, {} as ElFormContext)
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)
const $ELEMENT = useGlobalConfig()

View File

@@ -222,7 +222,7 @@ import {
computed,
} from 'vue'
import { ClickOutside } from '@element-plus/directives'
import { useFocus, useLocaleInject } from '@element-plus/hooks'
import { useFocus, useLocale } from '@element-plus/hooks'
import ElInput from '@element-plus/components/input'
import ElPopper, { Effect } from '@element-plus/components/popper'
import ElScrollbar from '@element-plus/components/scrollbar'
@@ -331,7 +331,7 @@ export default defineComponent({
],
setup(props, ctx) {
const { t } = useLocaleInject()
const { t } = useLocale()
const states = useSelectStates(props)
const {
optionsArray,

View File

@@ -13,7 +13,7 @@ import lodashDebounce from 'lodash/debounce'
import isEqual from 'lodash/isEqual'
import { UPDATE_MODEL_EVENT, CHANGE_EVENT } from '@element-plus/utils/constants'
import { EVENT_CODE } from '@element-plus/utils/aria'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import isServer from '@element-plus/utils/isServer'
import scrollIntoView from '@element-plus/utils/scroll-into-view'
import { isKorean } from '@element-plus/utils/isDef'
@@ -24,7 +24,7 @@ import type { QueryChangeCtx, SelectOptionProxy } from './token'
import type { ElFormContext, ElFormItemContext } from '@element-plus/tokens'
export function useSelectStates(props) {
const { t } = useLocaleInject()
const { t } = useLocale()
return reactive({
options: new Map(),
cachedOptions: new Map(),
@@ -57,7 +57,7 @@ type States = ReturnType<typeof useSelectStates>
export const useSelect = (props, states: States, ctx) => {
const ELEMENT = useGlobalConfig()
const { t } = useLocaleInject()
const { t } = useLocale()
// template refs
const reference = ref(null)

View File

@@ -87,7 +87,7 @@ import ElCheckbox from '@element-plus/components/checkbox'
import { ElIcon } from '@element-plus/components/icon'
import { ArrowDown, ArrowUp } from '@element-plus/icons'
import { ClickOutside } from '@element-plus/directives'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ElPopper, { Effect } from '@element-plus/components/popper'
import ElScrollbar from '@element-plus/components/scrollbar'
import type { Placement } from '@element-plus/components/popper'
@@ -128,7 +128,7 @@ export default defineComponent({
},
setup(props) {
const instance = getCurrentInstance()
const { t } = useLocaleInject()
const { t } = useLocale()
const parent = instance.parent as TableHeader
if (!parent.filterPanels.value[props.column.id]) {
parent.filterPanels.value[props.column.id] = instance

View File

@@ -260,7 +260,7 @@
import { defineComponent, getCurrentInstance, computed } from 'vue'
import debounce from 'lodash/debounce'
import { Mousewheel } from '@element-plus/directives'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { createStore } from './store/helper'
import TableLayout from './table-layout'
import TableHeader from './table-header'
@@ -306,7 +306,7 @@ export default defineComponent({
],
setup(props) {
type Row = typeof props.data[number]
const { t } = useLocaleInject()
const { t } = useLocale()
const table = getCurrentInstance() as Table<Row>
const store = createStore<Row>(table, props)
table.store = store

View File

@@ -146,7 +146,7 @@ import {
} from 'vue'
import dayjs from 'dayjs'
import isEqual from 'lodash/isEqual'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { ClickOutside } from '@element-plus/directives'
import { elFormKey, elFormItemKey } from '@element-plus/tokens'
import ElInput from '@element-plus/components/input'
@@ -227,7 +227,7 @@ export default defineComponent({
emits: ['update:modelValue', 'change', 'focus', 'blur', 'calendar-change'],
setup(props, ctx) {
const ELEMENT = useGlobalConfig()
const { lang } = useLocaleInject()
const { lang } = useLocale()
const elForm = inject(elFormKey, {} as ElFormContext)
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)

View File

@@ -44,7 +44,7 @@
import { defineComponent, ref, computed, inject } from 'vue'
import dayjs from 'dayjs'
import { EVENT_CODE } from '@element-plus/utils/aria'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import TimeSpinner from './basic-time-spinner.vue'
import { getAvailableArrs, useOldValue } from './useTimePicker'
@@ -77,7 +77,7 @@ export default defineComponent({
emits: ['pick', 'select-range', 'set-picker-option'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
// data
const selectionRange = ref([0, 2])
const oldValue = useOldValue(props)

View File

@@ -74,7 +74,7 @@
import { defineComponent, ref, computed, inject } from 'vue'
import dayjs from 'dayjs'
import union from 'lodash/union'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { EVENT_CODE } from '@element-plus/utils/aria'
import TimeSpinner from './basic-time-spinner.vue'
import { getAvailableArrs, useOldValue } from './useTimePicker'
@@ -107,7 +107,7 @@ export default defineComponent({
emits: ['pick', 'select-range', 'set-picker-option'],
setup(props, ctx) {
const { t, lang } = useLocaleInject()
const { t, lang } = useLocale()
const minDate = computed(() => props.parsedValue[0])
const maxDate = computed(() => props.parsedValue[1])
const oldValue = useOldValue(props)

View File

@@ -67,7 +67,7 @@ import {
import ElButton from '@element-plus/components/button'
import ElIcon from '@element-plus/components/icon'
import { elFormItemKey } from '@element-plus/tokens'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { UPDATE_MODEL_EVENT } from '@element-plus/utils/constants'
import { ArrowLeft, ArrowRight } from '@element-plus/icons'
import TransferPanel from './transfer-panel.vue'
@@ -161,7 +161,7 @@ export default defineComponent({
],
setup(props, { emit, slots }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const elFormItem = inject(elFormItemKey, {} as ElFormItemContext)
const checkedState = reactive({

View File

@@ -60,7 +60,7 @@
<script lang="ts">
import { computed, defineComponent, reactive, toRefs } from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { ElCheckbox, ElCheckboxGroup } from '@element-plus/components/checkbox'
import ElIcon from '@element-plus/components/icon'
import ElInput from '@element-plus/components/input'
@@ -83,7 +83,7 @@ export default defineComponent({
emits: [CHECKED_CHANGE_EVENT],
setup(props, { slots }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const panelState = reactive({
checked: [],

View File

@@ -43,7 +43,7 @@
<script lang="ts">
import { defineComponent, getCurrentInstance, provide } from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import { FixedSizeList } from '@element-plus/components/virtual-list'
import { useTree } from './composables/useTree'
import ElTreeNode from './tree-node.vue'
@@ -64,7 +64,7 @@ export default defineComponent({
props,
instance: getCurrentInstance(),
})
const { t } = useLocaleInject()
const { t } = useLocale()
const {
flattenTree,
isNotEmpty,

View File

@@ -42,7 +42,7 @@ import {
watch,
getCurrentInstance,
} from 'vue'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import TreeStore from './model/tree-store'
import { getNodeKey as getNodeKeyUtil } from './model/util'
import ElTreeNode from './tree-node.vue'
@@ -149,7 +149,7 @@ export default defineComponent({
'node-drag-over',
],
setup(props, ctx) {
const { t } = useLocaleInject()
const { t } = useLocale()
const store = ref<TreeStore>(
new TreeStore({

View File

@@ -103,7 +103,7 @@ import {
Check,
CircleCheck,
} from '@element-plus/icons'
import { useLocaleInject } from '@element-plus/hooks'
import { useLocale } from '@element-plus/hooks'
import ElProgress from '@element-plus/components/progress'
import type { PropType } from 'vue'
@@ -141,7 +141,7 @@ export default defineComponent({
},
emits: ['remove'],
setup(props, { emit }) {
const { t } = useLocaleInject()
const { t } = useLocale()
const handleClick = (file: UploadFile) => {
props.handlePreview(file)

View File

@@ -1,5 +1,5 @@
import { setConfig } from '@element-plus/utils/config'
import { LocaleInjectionKey, localeProviderMaker } from '@element-plus/hooks'
import { localeContextKey, localeProviderMaker } from '@element-plus/hooks'
import { version } from './version'
import type { App, Plugin } from 'vue'
@@ -25,7 +25,7 @@ const makeInstaller = (components: Plugin[] = []) => {
if (option.locale) {
const localeProvides = localeProviderMaker(opts.locale)
app.provide(LocaleInjectionKey, localeProvides)
app.provide(localeContextKey, localeProvides)
}
app.config.globalProperties.$ELEMENT = option

View File

@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils'
import useAttrs from '../use-attrs'
import { useAttrs } from '../use-attrs'
import type { ComponentOptions } from 'vue'
const CLASS = 'a'

View File

@@ -1,60 +0,0 @@
import { ref } from 'vue'
import { mount } from '@vue/test-utils'
import { useCssVar } from '..'
describe('usecssvar', () => {
test('Set css var on rootElement', () => {
mount({
template: `
<span></span>
`,
setup() {
const themeVars = ref({
'--el-button-default-bg-color': '#f44336',
'--el-button-default-text-color': '#2196f3',
})
useCssVar(themeVars)
},
})
const rootElement = window.document.documentElement
expect(
rootElement.style.getPropertyValue('--el-button-default-bg-color')
).toBe('#f44336')
expect(
rootElement.style.getPropertyValue('--el-button-default-text-color')
).toBe('#2196f3')
})
test('Set css var on custom Element', () => {
const wrapper = mount({
template: `
<span ref="elRef"></span>
`,
setup() {
const themeVars = ref({
'--el-span-default-bg-color': '#f44336',
'--el-span-default-text-color': '#2196f3',
})
const elRef = ref(null)
useCssVar(themeVars, elRef)
return {
elRef,
}
},
})
const customElement = wrapper.find('span').element
expect(
customElement.style.getPropertyValue('--el-span-default-bg-color')
).toBe('#f44336')
expect(
customElement.style.getPropertyValue('--el-span-default-text-color')
).toBe('#2196f3')
})
})

View File

@@ -1,5 +1,5 @@
import { ref } from 'vue'
import useFocus from '../use-focus'
import { useFocus } from '../use-focus'
describe('useFocus', () => {
it('should focus el', async () => {

View File

@@ -2,11 +2,11 @@ import { inject, h, nextTick } from 'vue'
import { mount } from '@vue/test-utils'
import Chinese from '@element-plus/locale/lang/zh-cn'
import English from '@element-plus/locale/lang/en'
import { useLocale, useLocaleProps, LocaleInjectionKey } from '../use-locale'
import { provideLocale, useLocaleProps, localeContextKey } from '../use-locale'
const TestComp = {
setup() {
const { t } = inject(LocaleInjectionKey)
const { t } = inject(localeContextKey)
return () => {
return h(
'div',
@@ -27,7 +27,7 @@ describe('use-locale', () => {
'el-test': TestComp,
},
setup(_, { slots }) {
useLocale()
provideLocale()
return () => slots.default()
},
},

View File

@@ -2,14 +2,14 @@ import { ref, nextTick, defineComponent, onMounted } from 'vue'
import { mount } from '@vue/test-utils'
import { hasClass } from '@element-plus/utils/dom'
import useLockScreen from '../use-lockscreen'
import { useLockscreen } from '../use-lockscreen'
const kls = 'el-popup-parent--hidden'
const Comp = defineComponent({
setup() {
const flag = ref(false)
useLockScreen(flag)
useLockscreen(flag)
onMounted(() => {
flag.value = true
})
@@ -17,7 +17,7 @@ const Comp = defineComponent({
template: `<div></div>`,
})
describe('useLockScreen', () => {
describe('useLockscreen', () => {
test('should lock screen when trigger is true', async () => {
const wrapper = mount({
template: `

View File

@@ -1,7 +1,7 @@
import { ref, nextTick } from 'vue'
import { EVENT_CODE } from '@element-plus/utils/aria'
import useModal from '../use-modal'
import { useModal } from '../use-modal'
describe('useModal', () => {
test('should work when ref value changed', async () => {

View File

@@ -1,7 +1,7 @@
import { ref } from 'vue'
import { on, off } from '@element-plus/utils/dom'
import triggerEvent from '@element-plus/test-utils/trigger-event'
import usePreventGlobal from '../use-prevent-global'
import { usePreventGlobal } from '../use-prevent-global'
describe('usePreventGlobal', () => {
const evtName = 'keydown'

View File

@@ -1,5 +1,5 @@
import { ref, nextTick } from 'vue'
import useRestoreActive from '../use-restore-active'
import { useRestoreActive } from '../use-restore-active'
describe('useRestoreActive', () => {
it('should restore active element', async () => {

View File

@@ -1,7 +1,7 @@
import { ref, nextTick, h } from 'vue'
import { mount } from '@vue/test-utils'
import useTeleport from '../use-teleport'
import { useTeleport } from '../use-teleport'
const AXIOM = 'Rem is the best girl'

View File

@@ -1,5 +1,5 @@
import { mount } from '@vue/test-utils'
import useTimeout from '../use-timeout'
import { useTimeout } from '../use-timeout'
const _mount = (cb: () => void) => {
return mount({

View File

@@ -1,101 +0,0 @@
import { defineComponent, Fragment, h, nextTick, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { getCssVariable } from '@element-plus/test-utils/dom'
import { useTransition, useTransitionProps } from '../use-transition'
const transitionShow = 'show'
const transitionHide = 'hide'
describe('use-transition', () => {
const TestComp = defineComponent({
props: useTransitionProps,
setup(props) {
const indicator = ref(false)
const { transitionStyle, transition } = useTransition(props, indicator)
const toggle = () => (indicator.value = !indicator.value)
return () => {
return h(Fragment, { key: 0 }, [
h(
'div',
{
style: transitionStyle.value,
class: 'content',
},
transition.value
),
h(
'button',
{
onClick: toggle,
class: 'toggle',
},
'toggle'
),
])
}
},
})
let wrapper
beforeEach(() => {
wrapper = mount(TestComp, {
props: {
transitionShow,
transitionHide,
},
})
})
afterEach(() => {
wrapper.unmount()
})
it('should render correctly', async () => {
expect(wrapper.find('.content').text()).toBe(
`el-transition--${transitionHide}`
)
expect(
getCssVariable(
wrapper.find('.content').element,
'--el-transition-duration'
)
).toBe('0.3s')
})
it('should be able to update transition class', async () => {
expect(wrapper.find('.content').text()).toBe(
`el-transition--${transitionHide}`
)
await wrapper.find('.toggle').trigger('click') // this tick indicator gets changed
await nextTick() // this tick the inner value transitionState gets changed
await nextTick() // this tick the computed value gets updated
expect(wrapper.find('.content').text()).toBe(
`el-transition--${transitionShow}`
)
})
it('should be able to change the transition duration via props', async () => {
expect(wrapper.find('.content').text()).toBe(
`el-transition--${transitionHide}`
)
expect(
getCssVariable(
wrapper.find('.content').element,
'--el-transition-duration'
)
).toBe('0.3s')
await wrapper.setProps({
transitionDuration: 0.2,
})
expect(
getCssVariable(
wrapper.find('.content').element,
'--el-transition-duration'
)
).toBe('0.2s')
})
})

View File

@@ -1,18 +1,15 @@
export { default as useAttrs } from './use-attrs'
export { default as useEvents } from './use-events'
export { default as useLockScreen } from './use-lockscreen'
export { default as useRestoreActive } from './use-restore-active'
export { default as useModal } from './use-modal'
export { default as useMigrating } from './use-migrating'
export { default as useFocus } from './use-focus'
export { default as useThrottleRender } from './use-throttle-render'
export { default as usePreventGlobal } from './use-prevent-global'
export { default as useTeleport } from './use-teleport'
export { default as useTimeout } from './use-timeout'
export * from './use-attrs'
export * from './use-focus'
export * from './use-form-item'
export * from './use-global-config'
export * from './use-locale'
export * from './use-lockscreen'
export * from './use-modal'
export * from './use-model-toggle'
export * from './use-popper'
export * from './use-css-var'
export * from './use-locale'
export * from './use-form-item'
export * from './use-prevent-global'
export * from './use-restore-active'
export * from './use-same-target'
export * from './use-global-config'
export * from './use-teleport'
export * from './use-throttle-render'
export * from './use-timeout'

View File

@@ -12,7 +12,9 @@ interface Params {
const DEFAULT_EXCLUDE_KEYS = ['class', 'style']
const LISTENER_PREFIX = /^on[A-Z]/
export default (params: Params = {}): ComputedRef<Record<string, unknown>> => {
export const useAttrs = (
params: Params = {}
): ComputedRef<Record<string, unknown>> => {
const { excludeListeners = false, excludeKeys = [] } = params
const allExcludeKeys = excludeKeys.concat(DEFAULT_EXCLUDE_KEYS)

View File

@@ -1,102 +0,0 @@
import {
watch,
isRef,
onMounted,
computed,
unref,
inject,
onUnmounted,
provide,
ref,
} from 'vue'
import type { Ref, WatchStopHandle, InjectionKey } from 'vue'
type VarsType = Ref<Record<string, string>> | Record<string, string>
const VAR_PREFIX = '--el-'
const setVars = (target: HTMLElement, val: Record<string, string>) => {
Object.keys(val).forEach((key) => {
if (key.startsWith(VAR_PREFIX)) {
target?.style.setProperty(key, val[key])
} else {
target?.style.setProperty(VAR_PREFIX + key, val[key])
}
})
}
export const themeVarsKey: InjectionKey<VarsType> = 'themeVars' as any
/**
* @param vars
* @param target
* @returns stopWatchHandler
* @example
*
* If you pass a Ref vars param, it will generate a watch handler.
*
* In main.ts:
*
* ```ts
* const themeVars = {
* '--el-color-primary': '#f44336',
* '--el-color-white': '#2196f3',
* }
* app.provide(themeVarsKey, themeVars)
* ```
* Usually you need to use this function in the root component.
* In components' steup:
*
* ```ts
* setup() {
* const themeVars = ref({
* '--el-button-default-bg-color': '#f44336',
* '--el-button-default-text-color': '#2196f3',
* })
* useCssVar(themeVars)
* }
* ```
*/
export function useCssVar(
vars: VarsType,
target?: Ref<HTMLElement> | HTMLElement
) {
let stopWatchCssVar: WatchStopHandle | null = null
const elRef = computed(
() => unref(target) || window?.document?.documentElement
)
const themeVars = useThemeVars()
const customVars = { ...themeVars, ...unref(vars) }
provide(themeVarsKey, ref(customVars))
onMounted(() => {
isRef(vars)
? (stopWatchCssVar = watch(
vars,
(val) => {
setVars(elRef.value, {
...unref(themeVars),
...val,
})
},
{
immediate: true,
deep: true,
}
))
: setVars(elRef.value, {
...unref(themeVars),
...vars,
})
})
onUnmounted(() => stopWatchCssVar && stopWatchCssVar())
}
export const useThemeVars = () => {
const themeVars = inject(themeVarsKey, {})
return themeVars
}

View File

@@ -1,23 +0,0 @@
import { watch } from 'vue'
import { on, off } from '@element-plus/utils/dom'
import type { Ref } from 'vue'
export type Event = {
name: string
handler: (...args: any[]) => any
}
export default (el: Ref<HTMLElement>, events: Event[]) => {
watch(el, (val) => {
if (val) {
events.forEach(({ name, handler }) => {
on(el.value, name, handler)
})
} else {
events.forEach(({ name, handler }) => {
off(el.value, name, handler)
})
}
})
}

View File

@@ -1,6 +1,6 @@
import type { Ref } from 'vue'
export default (el: Ref<HTMLElement>) => {
export const useFocus = (el: Ref<HTMLElement>) => {
return {
focus: () => {
el.value?.focus?.()

View File

@@ -1,12 +1,12 @@
import { inject, computed, getCurrentInstance, unref } from 'vue'
import { elFormKey, elFormItemKey } from '@element-plus/tokens'
import { buildProps } from '@element-plus/utils/props'
import { buildProps, componentSize } from '@element-plus/utils/props'
import { useGlobalConfig } from '@element-plus/utils/util'
import type { ExtractPropTypes } from 'vue'
import type { MaybeRef } from '@vueuse/core'
const sizes = ['', 'large', 'medium', 'small', 'mini'] as const
const sizes = ['', ...componentSize] as const
export const useFormItemProps = buildProps({
size: {
@@ -16,7 +16,6 @@ export const useFormItemProps = buildProps({
},
disabled: Boolean,
} as const)
export type UseFormItemProps = ExtractPropTypes<typeof useFormItemProps>
export type LocalFallbacks = {
@@ -24,11 +23,10 @@ export type LocalFallbacks = {
disabled?: MaybeRef<UseFormItemProps['disabled'] | undefined>
}
export const useFormItem = ({ size, disabled }: LocalFallbacks) => {
export const useFormItem = ({ size, disabled }: LocalFallbacks = {}) => {
const vm = getCurrentInstance()!
const $ELEMENT = useGlobalConfig()
// vm.props is not reactive so we use the reactive one here.
const props = vm.proxy?.$props as UseFormItemProps
const form = inject(elFormKey, undefined)
const formItem = inject(elFormItemKey, undefined)

View File

@@ -8,6 +8,5 @@ const defaultConfig: ConfigProvdierContext = {
},
}
export const useGlobalConfig = () => {
return inject(configProviderContextKey, defaultConfig)
}
export const useGlobalConfig = () =>
inject(configProviderContextKey, defaultConfig)

View File

@@ -1,66 +1,46 @@
import { computed, getCurrentInstance, inject, provide, ref } from 'vue'
import { computed, getCurrentInstance, inject, provide, ref, unref } from 'vue'
import get from 'lodash/get'
import English from '@element-plus/locale/lang/en'
import { buildProp, definePropType } from '@element-plus/utils/props'
import { buildProps, definePropType } from '@element-plus/utils/props'
import type { MaybeRef } from '@vueuse/core'
import type { InjectionKey, Ref } from 'vue'
import type { Language } from '@element-plus/locale'
export const useLocaleProps = {
locale: buildProp({
export const useLocaleProps = buildProps({
locale: {
type: definePropType<Language>(Object),
}),
}
type Translator = (...args: any[]) => string
},
})
export type Translator = (path: string) => string
export type LocaleContext = {
locale: Ref<Language>
lang: Ref<string>
t: Translator
}
export const LocaleInjectionKey =
'ElLocaleInjection' as unknown as InjectionKey<LocaleContext>
export const localeContextKey: InjectionKey<LocaleContext> =
Symbol('localeContextKey')
// this is meant to fix global methods like `ElMessage(opts)`, this way we can inject current locale
// into the component as default injection value.
// refer to: https://github.com/element-plus/element-plus/issues/2610#issuecomment-887965266
let localeObjCache: LocaleContext
let localeContextCache: LocaleContext
function translate(path, option, current) {
const paths = path.split('.')
let value
for (let i = 0, j = paths.length; i < j; i++) {
const property = paths[i]
value = current[property]
if (i === j - 1) return template(value, option)
if (!value) return ''
current = value
}
}
export const useLocale = () => {
export const provideLocale = () => {
const vm = getCurrentInstance()!
const props = vm.props as {
locale: Language
}
const locale = computed(() => props.locale || English)
const lang = computed(() => locale.value.name)
const _translator = (...args: any[]) => {
const [path, option] = args
return translate(path, option, locale.value)
}
const t = (...args: any[]) => {
return _translator(...args)
}
const provides = {
const t = buildTranslator(locale)
const provides: LocaleContext = {
locale,
lang,
t,
} as LocaleContext
}
// this could be broken if someone tries to do following:
@@ -71,16 +51,17 @@ export const useLocale = () => {
* </config-provider>
* </config-provider>
*/
localeObjCache = provides
provide(LocaleInjectionKey, provides)
localeContextCache = provides
provide(localeContextKey, provides)
}
function template(str: string, option) {
if (!str || !option) return str
return str.replace(/\{(\w+)\}/g, (_, key) => {
return option[key]
})
}
export const buildTranslator =
(locale: MaybeRef<Language>): Translator =>
(path) =>
translate(path, unref(locale))
export const translate = (path: string, locale: Language): string =>
get(locale, path, '')
export const localeProviderMaker = (locale = English) => {
const lang = ref(locale.name)
@@ -88,23 +69,13 @@ export const localeProviderMaker = (locale = English) => {
return {
lang,
locale: localeRef,
t: (...args: any[]) => {
const [path, option] = args
return translate(path, option, localeRef.value)
},
t: buildTranslator(localeRef),
}
}
export const useLocaleInject = () => {
export const useLocale = () => {
return inject(
LocaleInjectionKey,
localeObjCache || {
lang: ref(English.name),
locale: ref(English),
t: (...args) => {
const [path, option] = args
return translate(path, option, English)
},
}
localeContextKey,
localeContextCache || localeProviderMaker(English)
)
}

View File

@@ -1,4 +1,4 @@
import { watch, isRef, onUnmounted } from 'vue'
import { watch, isRef, onScopeDispose } from 'vue'
import getScrollBarWidth from '@element-plus/utils/scrollbar-width'
import { throwError } from '@element-plus/utils/error'
@@ -16,10 +16,10 @@ import type { Ref } from 'vue'
* When the trigger became true, it assumes modal is now opened and vice versa.
* @param trigger {Ref<boolean>}
*/
export default (trigger: Ref<boolean>) => {
export const useLockscreen = (trigger: Ref<boolean>) => {
if (!isRef(trigger)) {
throwError(
'[useLockScreen]',
'[useLockscreen]',
'You need to pass a ref param to this function'
)
}
@@ -28,10 +28,6 @@ export default (trigger: Ref<boolean>) => {
let bodyPaddingRight = '0'
let computedBodyPaddingRight = 0
onUnmounted(() => {
cleanup()
})
const cleanup = () => {
removeClass(document.body, 'el-popup-parent--hidden')
if (withoutHiddenClass) {
@@ -39,31 +35,33 @@ export default (trigger: Ref<boolean>) => {
}
}
watch(trigger, (val) => {
if (val) {
withoutHiddenClass = !hasClass(document.body, 'el-popup-parent--hidden')
if (withoutHiddenClass) {
bodyPaddingRight = document.body.style.paddingRight
computedBodyPaddingRight = parseInt(
getStyle(document.body, 'paddingRight'),
10
)
}
scrollBarWidth = getScrollBarWidth()
const bodyHasOverflow =
document.documentElement.clientHeight < document.body.scrollHeight
const bodyOverflowY = getStyle(document.body, 'overflowY')
if (
scrollBarWidth > 0 &&
(bodyHasOverflow || bodyOverflowY === 'scroll') &&
withoutHiddenClass
) {
document.body.style.paddingRight = `${
computedBodyPaddingRight + scrollBarWidth
}px`
}
addClass(document.body, 'el-popup-parent--hidden')
} else {
if (!val) {
cleanup()
return
}
withoutHiddenClass = !hasClass(document.body, 'el-popup-parent--hidden')
if (withoutHiddenClass) {
bodyPaddingRight = document.body.style.paddingRight
computedBodyPaddingRight = parseInt(
getStyle(document.body, 'paddingRight'),
10
)
}
scrollBarWidth = getScrollBarWidth()
const bodyHasOverflow =
document.documentElement.clientHeight < document.body.scrollHeight
const bodyOverflowY = getStyle(document.body, 'overflowY')
if (
scrollBarWidth > 0 &&
(bodyHasOverflow || bodyOverflowY === 'scroll') &&
withoutHiddenClass
) {
document.body.style.paddingRight = `${
computedBodyPaddingRight + scrollBarWidth
}px`
}
addClass(document.body, 'el-popup-parent--hidden')
})
onScopeDispose(() => cleanup())
}

View File

@@ -1,35 +0,0 @@
import { getCurrentInstance, onMounted } from 'vue'
import { debugWarn } from '@element-plus/utils/error'
import { kebabCase } from '@element-plus/utils/util'
const useMigrating = function () {
onMounted(() => {
const instance = getCurrentInstance()!
if (process.env.NODE_ENV === 'production') return
if (!instance.vnode) return
const { props = {} } = getMigratingConfig()
const { data } = instance
const definedProps = data.attrs || {}
for (let propName in definedProps as any) {
propName = kebabCase(propName) // compatible with camel case
if (props[propName]) {
debugWarn(
'Element Migrating',
`[${instance.proxy?.$options.name}][Attribute]: ${props[propName]}`
)
}
}
})
const getMigratingConfig = function () {
return {
props: {},
events: {},
}
}
return {
getMigratingConfig,
}
}
export default useMigrating

View File

@@ -1,9 +1,8 @@
import { watch } from 'vue'
import { on } from '@element-plus/utils/dom'
import { isClient, useEventListener } from '@vueuse/core'
import { EVENT_CODE } from '@element-plus/utils/aria'
import isServer from '@element-plus/utils/isServer'
import type { Ref, ComputedRef } from 'vue'
import type { Ref } from 'vue'
type ModalInstance = {
handleClose: () => void
@@ -20,25 +19,17 @@ const closeModal = (e: KeyboardEvent) => {
}
}
export default (
instance: ModalInstance,
visibleRef: Ref<boolean> | ComputedRef
) => {
watch(
() => visibleRef.value,
(val) => {
if (val) {
modalStack.push(instance)
} else {
modalStack.splice(
modalStack.findIndex((modal) => modal === instance),
1
)
}
export const useModal = (instance: ModalInstance, visibleRef: Ref<boolean>) => {
watch(visibleRef, (val) => {
if (val) {
modalStack.push(instance)
} else {
modalStack.splice(
modalStack.findIndex((modal) => modal === instance),
1
)
}
)
})
}
if (!isServer) {
on(document, 'keydown', closeModal)
}
if (isClient) useEventListener(document, 'keydown', closeModal)

View File

@@ -3,17 +3,19 @@ import { isFunction } from '@vue/shared'
import { isBool } from '@element-plus/utils/util'
import { UPDATE_MODEL_EVENT } from '@element-plus/utils/constants'
import isServer from '@element-plus/utils/isServer'
import { buildProps, definePropType } from '@element-plus/utils/props'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import type { Ref, ComponentPublicInstance } from 'vue'
import type { Ref, ComponentPublicInstance, ExtractPropTypes } from 'vue'
export const useModelToggleProps = {
export const useModelToggleProps = buildProps({
modelValue: {
type: Boolean,
type: definePropType<boolean | null>(Boolean),
default: null,
},
'onUpdate:modelValue': Function,
}
})
export type UseModelToggleProps = ExtractPropTypes<typeof useModelToggleProps>
export const useModelToggleEmits = [UPDATE_MODEL_EVENT]
@@ -32,7 +34,9 @@ export const useModelToggle = ({
onShow,
onHide,
}: ModelToggleParams) => {
const { appContext, props, proxy, emit } = getCurrentInstance()!
const instance = getCurrentInstance()!
const props = instance.props as UseModelToggleProps & { disabled: boolean }
const { emit } = instance
const hasUpdateHandler = computed(() =>
isFunction(props['onUpdate:modelValue'])
@@ -124,13 +128,13 @@ export const useModelToggle = ({
if (
shouldHideWhenRouteChanges &&
appContext.config.globalProperties.$route !== undefined
instance.appContext.config.globalProperties.$route !== undefined
) {
watch(
() => ({
...(
proxy as ComponentPublicInstance<{
$route: any
instance.proxy as ComponentPublicInstance<{
$route: RouteLocationNormalizedLoaded
}>
).$route,
}),

View File

@@ -26,8 +26,8 @@ import { stop } from '@element-plus/utils/dom'
import PopupManager from '@element-plus/utils/popup-manager'
import { throwError } from '@element-plus/utils/error'
import useTeleport from '../use-teleport'
import useTimeout from '../use-timeout'
import { useTeleport } from '../use-teleport'
import { useTimeout } from '../use-timeout'
import { useModelToggle } from '../use-model-toggle'
import { useTransitionFallthrough } from '../use-transition-fallthrough'
import { defaultPopperOptions, defaultModifiers } from './use-popper-options'

View File

@@ -1,25 +1,23 @@
import { watch } from 'vue'
import { on, off } from '@element-plus/utils/dom'
import { useEventListener } from '@vueuse/core'
import type { Ref } from 'vue'
export default (
export const usePreventGlobal = <E extends keyof DocumentEventMap>(
indicator: Ref<boolean>,
evt: string,
cb: (e: Event) => boolean
evt: E,
cb: (e: DocumentEventMap[E]) => boolean
) => {
const prevent = (e: Event) => {
if (cb(e)) {
e.stopImmediatePropagation()
}
const prevent = (e: DocumentEventMap[E]) => {
if (cb(e)) e.stopImmediatePropagation()
}
let stop: (() => void) | undefined = undefined
watch(
() => indicator.value,
(val) => {
if (val) {
on(document, evt, prevent, true)
stop = useEventListener(document, evt, prevent, true)
} else {
off(document, evt, prevent, true)
stop?.()
}
},
{ immediate: true }

View File

@@ -5,7 +5,10 @@ import type { Ref } from 'vue'
* This method provides dialogable components the ability to restore previously activated element before
* the dialog gets opened
*/
export default (toggle: Ref<boolean>, initialFocus?: Ref<HTMLElement>) => {
export const useRestoreActive = (
toggle: Ref<boolean>,
initialFocus?: Ref<HTMLElement>
) => {
let previousActive: HTMLElement
watch(
() => toggle.value,

View File

@@ -1,6 +1,6 @@
import { h, ref, Teleport, onUnmounted } from 'vue'
import { NOOP } from '@vue/shared'
import isServer from '@element-plus/utils/isServer'
import { isClient } from '@vueuse/core'
import {
createGlobalNode,
removeGlobalNode,
@@ -8,10 +8,13 @@ import {
import type { VNode, Ref } from 'vue'
export default (contentRenderer: () => VNode, appendToBody: Ref<boolean>) => {
export const useTeleport = (
contentRenderer: () => VNode,
appendToBody: Ref<boolean>
) => {
const isTeleportVisible = ref(false)
if (isServer) {
if (!isClient) {
return {
isTeleportVisible,
showTeleport: NOOP,

View File

@@ -1,12 +1,11 @@
import { onMounted, ref, watch } from 'vue'
import type { Ref } from 'vue'
import type { TimeoutHandle } from '@element-plus/utils/types'
export default function (loading: Ref<boolean>, throttle = 0) {
export const useThrottleRender = (loading: Ref<boolean>, throttle = 0) => {
if (throttle === 0) return loading
const throttled = ref(false)
let timeoutHandle: TimeoutHandle = 0
let timeoutHandle = 0
const dispatchThrottling = () => {
if (timeoutHandle) {

View File

@@ -1,22 +1,18 @@
import { onBeforeUnmount } from 'vue'
import { tryOnScopeDispose } from '@vueuse/core'
import type { TimeoutHandle } from '@element-plus/utils/types'
export function useTimeout() {
let timeoutHandle: number
export default function () {
let timeoutHandle: TimeoutHandle
const registerTimeout = (fn: (...args: any[]) => any, delay: number) => {
cancelTimeout()
timeoutHandle = window.setTimeout(fn, delay)
}
const cancelTimeout = () => window.clearTimeout(timeoutHandle)
onBeforeUnmount(() => {
clearTimeout(timeoutHandle)
})
tryOnScopeDispose(() => cancelTimeout())
return {
registerTimeout: (fn: (...args: any[]) => unknown, delay: number) => {
clearTimeout(timeoutHandle)
timeoutHandle = setTimeout(fn, delay) as any as TimeoutHandle
},
cancelTimeout: () => {
clearTimeout(timeoutHandle)
},
registerTimeout,
cancelTimeout,
}
}

View File

@@ -25,7 +25,7 @@ export const useTransitionFallthroughEmits = [
ENTER_CANCELLED,
LEAVE,
LEAVE_CANCELLED,
]
] as const
// Sometimes we want to delegate the transition emitted event
// we have to right the function locally, which is not a good
@@ -59,7 +59,7 @@ export const useTransitionFallthroughEmits = [
*/
export const useTransitionFallthrough = () => {
const { emit } = getCurrentInstance()
const { emit } = getCurrentInstance()!
return {
onAfterAppear: () => {

View File

@@ -1,33 +0,0 @@
import { computed, ref, watch, nextTick } from 'vue'
import type { ExtractPropTypes, Ref } from 'vue'
export const useTransitionProps = {
transitionDuration: {
type: Number,
default: 0.3,
},
transitionShow: String,
transitionHide: String,
}
export const useTransition = (
props: ExtractPropTypes<typeof useTransitionProps>,
indicator: Ref<boolean>
) => {
const transitionState = ref(indicator.value)
watch(indicator, (val) => {
nextTick(() => (transitionState.value = val))
})
return {
transition: computed(() => {
return `el-transition--${
transitionState.value ? props.transitionShow : props.transitionHide
}`
}),
transitionStyle: computed(
() => `--el-transition-duration: ${props.transitionDuration}s`
),
}
}