mirror of
https://github.com/element-plus/element-plus.git
synced 2025-01-18 10:59:10 +08:00
refactor(component): improve code (#7959)
This commit is contained in:
parent
ff5ea7e2ed
commit
3adb0f2077
@ -1,5 +1,4 @@
|
||||
[
|
||||
"packages/components/autocomplete/",
|
||||
"packages/components/cascader-panel/",
|
||||
"packages/components/cascader/",
|
||||
"packages/components/checkbox/",
|
||||
|
@ -5,12 +5,10 @@
|
||||
:class="[ns.b(), ns.m(type), ns.is('center', center), ns.is(effect)]"
|
||||
role="alert"
|
||||
>
|
||||
<el-icon
|
||||
v-if="showIcon && iconComponent"
|
||||
:class="[ns.e('icon'), isBigIcon]"
|
||||
>
|
||||
<el-icon v-if="showIcon && iconComponent" :class="iconClass">
|
||||
<component :is="iconComponent" />
|
||||
</el-icon>
|
||||
|
||||
<div :class="ns.e('content')">
|
||||
<span
|
||||
v-if="title || $slots.title"
|
||||
@ -58,21 +56,21 @@ const slots = useSlots()
|
||||
|
||||
const ns = useNamespace('alert')
|
||||
|
||||
// state
|
||||
const visible = ref(true)
|
||||
|
||||
// computed
|
||||
const iconComponent = computed(
|
||||
() => TypeComponentsMap[props.type] || TypeComponentsMap['info']
|
||||
)
|
||||
const isBigIcon = computed(
|
||||
() => props.description || { [ns.is('big')]: slots.default }
|
||||
)
|
||||
|
||||
const iconClass = computed(() => [
|
||||
ns.e('icon'),
|
||||
{ [ns.is('big')]: !!props.description || !!slots.default },
|
||||
])
|
||||
|
||||
const isBoldTitle = computed(
|
||||
() => props.description || { [ns.is('bold')]: slots.default }
|
||||
)
|
||||
|
||||
// methods
|
||||
const close = (evt: MouseEvent) => {
|
||||
visible.value = false
|
||||
emit('close', evt)
|
||||
|
@ -6,13 +6,18 @@ import {
|
||||
isString,
|
||||
} from '@element-plus/utils'
|
||||
import { useTooltipContentProps } from '@element-plus/components/tooltip'
|
||||
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
import {
|
||||
CHANGE_EVENT,
|
||||
INPUT_EVENT,
|
||||
UPDATE_MODEL_EVENT,
|
||||
} from '@element-plus/constants'
|
||||
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import type Autocomplete from './autocomplete.vue'
|
||||
import type { Placement } from '@element-plus/components/popper'
|
||||
import type { Awaitable } from '@element-plus/utils'
|
||||
|
||||
export type AutocompleteData = { value: string }[]
|
||||
export type AutocompleteData = Record<string, any>[]
|
||||
export type AutocompleteFetchSuggestionsCallback = (
|
||||
data: AutocompleteData
|
||||
) => void
|
||||
@ -81,8 +86,8 @@ export type AutocompleteProps = ExtractPropTypes<typeof autocompleteProps>
|
||||
|
||||
export const autocompleteEmits = {
|
||||
[UPDATE_MODEL_EVENT]: (value: string) => isString(value),
|
||||
input: (value: string) => isString(value),
|
||||
change: (value: string) => isString(value),
|
||||
[INPUT_EVENT]: (value: string) => isString(value),
|
||||
[CHANGE_EVENT]: (value: string) => isString(value),
|
||||
focus: (evt: FocusEvent) => evt instanceof FocusEvent,
|
||||
blur: (evt: FocusEvent) => evt instanceof FocusEvent,
|
||||
clear: () => true,
|
||||
|
@ -95,19 +95,25 @@ import {
|
||||
nextTick,
|
||||
onMounted,
|
||||
ref,
|
||||
useAttrs as useCompAttrs,
|
||||
useAttrs as useRawAttrs,
|
||||
} from 'vue'
|
||||
import { debounce } from 'lodash-unified'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
import { useAttrs, useNamespace } from '@element-plus/hooks'
|
||||
import { generateId, isArray, throwError } from '@element-plus/utils'
|
||||
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
import {
|
||||
CHANGE_EVENT,
|
||||
INPUT_EVENT,
|
||||
UPDATE_MODEL_EVENT,
|
||||
} from '@element-plus/constants'
|
||||
import ElInput from '@element-plus/components/input'
|
||||
import ElScrollbar from '@element-plus/components/scrollbar'
|
||||
import ElTooltip from '@element-plus/components/tooltip'
|
||||
import ElIcon from '@element-plus/components/icon'
|
||||
import { Loading } from '@element-plus/icons-vue'
|
||||
import { autocompleteEmits, autocompleteProps } from './autocomplete'
|
||||
import type { AutocompleteData } from './autocomplete'
|
||||
|
||||
import type { StyleValue } from 'vue'
|
||||
import type { TooltipInstance } from '@element-plus/components/tooltip'
|
||||
import type { InputInstance } from '@element-plus/components/input'
|
||||
@ -122,73 +128,71 @@ const COMPONENT_NAME = 'ElAutocomplete'
|
||||
const props = defineProps(autocompleteProps)
|
||||
const emit = defineEmits(autocompleteEmits)
|
||||
|
||||
const ns = useNamespace('autocomplete')
|
||||
let isClear = false
|
||||
const attrs = useAttrs()
|
||||
const compAttrs = useCompAttrs()
|
||||
const suggestions = ref<any[]>([])
|
||||
const highlightedIndex = ref(-1)
|
||||
const dropdownWidth = ref('')
|
||||
const activated = ref(false)
|
||||
const suggestionDisabled = ref(false)
|
||||
const loading = ref(false)
|
||||
const rawAttrs = useRawAttrs()
|
||||
const ns = useNamespace('autocomplete')
|
||||
|
||||
const inputRef = ref<InputInstance>()
|
||||
const regionRef = ref<HTMLElement>()
|
||||
const popperRef = ref<TooltipInstance>()
|
||||
const listboxRef = ref<HTMLElement>()
|
||||
|
||||
const listboxId = computed(() => {
|
||||
return ns.b(String(generateId()))
|
||||
})
|
||||
const styles = computed(() => compAttrs.style as StyleValue)
|
||||
let isClear = false
|
||||
const suggestions = ref<AutocompleteData>([])
|
||||
const highlightedIndex = ref(-1)
|
||||
const dropdownWidth = ref('')
|
||||
const activated = ref(false)
|
||||
const suggestionDisabled = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
const listboxId = computed(() => ns.b(String(generateId())))
|
||||
const styles = computed(() => rawAttrs.style as StyleValue)
|
||||
|
||||
const suggestionVisible = computed(() => {
|
||||
const isValidData = isArray(suggestions.value) && suggestions.value.length > 0
|
||||
const isValidData = suggestions.value.length > 0
|
||||
return (isValidData || loading.value) && activated.value
|
||||
})
|
||||
const suggestionLoading = computed(() => {
|
||||
return !props.hideLoading && loading.value
|
||||
})
|
||||
|
||||
const onSuggestionShow = () => {
|
||||
nextTick(() => {
|
||||
if (suggestionVisible.value) {
|
||||
dropdownWidth.value = `${inputRef.value!.$el.offsetWidth}px`
|
||||
}
|
||||
})
|
||||
const suggestionLoading = computed(() => !props.hideLoading && loading.value)
|
||||
|
||||
const onSuggestionShow = async () => {
|
||||
await nextTick()
|
||||
if (suggestionVisible.value) {
|
||||
dropdownWidth.value = `${inputRef.value!.$el.offsetWidth}px`
|
||||
}
|
||||
}
|
||||
|
||||
const getData = async (queryString: string) => {
|
||||
if (suggestionDisabled.value) {
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
const cb = (suggestionsArg: any[]) => {
|
||||
if (suggestionDisabled.value) return
|
||||
|
||||
const cb = (suggestionList: AutocompleteData) => {
|
||||
loading.value = false
|
||||
if (suggestionDisabled.value) {
|
||||
return
|
||||
}
|
||||
if (isArray(suggestionsArg)) {
|
||||
suggestions.value = suggestionsArg
|
||||
if (suggestionDisabled.value) return
|
||||
|
||||
if (isArray(suggestionList)) {
|
||||
suggestions.value = suggestionList
|
||||
highlightedIndex.value = props.highlightFirstItem ? 0 : -1
|
||||
} else {
|
||||
throwError(COMPONENT_NAME, 'autocomplete suggestions must be an array')
|
||||
}
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
if (isArray(props.fetchSuggestions)) {
|
||||
cb(props.fetchSuggestions)
|
||||
} else {
|
||||
const result = await props.fetchSuggestions(queryString, cb)
|
||||
if (isArray(result)) {
|
||||
cb(result)
|
||||
}
|
||||
if (isArray(result)) cb(result)
|
||||
}
|
||||
}
|
||||
const debouncedGetData = debounce(getData, props.debounce)
|
||||
const handleInput = (value: string) => {
|
||||
const valuePresented = Boolean(value)
|
||||
|
||||
emit('input', value)
|
||||
const handleInput = (value: string) => {
|
||||
const valuePresented = !!value
|
||||
|
||||
emit(INPUT_EVENT, value)
|
||||
emit(UPDATE_MODEL_EVENT, value)
|
||||
|
||||
suggestionDisabled.value = false
|
||||
activated.value ||= isClear && valuePresented
|
||||
|
||||
@ -202,9 +206,11 @@ const handleInput = (value: string) => {
|
||||
}
|
||||
debouncedGetData(value)
|
||||
}
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
emit('change', value)
|
||||
emit(CHANGE_EVENT, value)
|
||||
}
|
||||
|
||||
const handleFocus = (evt: FocusEvent) => {
|
||||
activated.value = true
|
||||
emit('focus', evt)
|
||||
@ -212,16 +218,19 @@ const handleFocus = (evt: FocusEvent) => {
|
||||
debouncedGetData(String(props.modelValue))
|
||||
}
|
||||
}
|
||||
|
||||
const handleBlur = (evt: FocusEvent) => {
|
||||
emit('blur', evt)
|
||||
}
|
||||
|
||||
const handleClear = () => {
|
||||
activated.value = false
|
||||
isClear = true
|
||||
emit(UPDATE_MODEL_EVENT, '')
|
||||
emit('clear')
|
||||
}
|
||||
const handleKeyEnter = () => {
|
||||
|
||||
const handleKeyEnter = async () => {
|
||||
if (
|
||||
suggestionVisible.value &&
|
||||
highlightedIndex.value >= 0 &&
|
||||
@ -230,19 +239,20 @@ const handleKeyEnter = () => {
|
||||
handleSelect(suggestions.value[highlightedIndex.value])
|
||||
} else if (props.selectWhenUnmatched) {
|
||||
emit('select', { value: props.modelValue })
|
||||
nextTick(() => {
|
||||
suggestions.value = []
|
||||
highlightedIndex.value = -1
|
||||
})
|
||||
await nextTick()
|
||||
suggestions.value = []
|
||||
highlightedIndex.value = -1
|
||||
}
|
||||
}
|
||||
const handleKeyEscape = (e) => {
|
||||
|
||||
const handleKeyEscape = (evt: Event) => {
|
||||
if (suggestionVisible.value) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
evt.preventDefault()
|
||||
evt.stopPropagation()
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
activated.value = false
|
||||
}
|
||||
@ -251,23 +261,23 @@ const focus = () => {
|
||||
inputRef.value?.focus()
|
||||
}
|
||||
|
||||
const handleSelect = (item: any) => {
|
||||
emit('input', item[props.valueKey])
|
||||
const handleSelect = async (item: any) => {
|
||||
emit(INPUT_EVENT, item[props.valueKey])
|
||||
emit(UPDATE_MODEL_EVENT, item[props.valueKey])
|
||||
emit('select', item)
|
||||
nextTick(() => {
|
||||
suggestions.value = []
|
||||
highlightedIndex.value = -1
|
||||
})
|
||||
await nextTick()
|
||||
suggestions.value = []
|
||||
highlightedIndex.value = -1
|
||||
}
|
||||
|
||||
const highlight = (index: number) => {
|
||||
if (!suggestionVisible.value || loading.value) {
|
||||
return
|
||||
}
|
||||
if (!suggestionVisible.value || loading.value) return
|
||||
|
||||
if (index < 0) {
|
||||
highlightedIndex.value = -1
|
||||
return
|
||||
}
|
||||
|
||||
if (index >= suggestions.value.length) {
|
||||
index = suggestions.value.length - 1
|
||||
}
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { buildProps, definePropType, iconPropType } from '@element-plus/utils'
|
||||
import {
|
||||
buildProps,
|
||||
definePropType,
|
||||
iconPropType,
|
||||
isNumber,
|
||||
} from '@element-plus/utils'
|
||||
import { componentSizes } from '@element-plus/constants'
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import type { ObjectFitProperty } from 'csstype'
|
||||
@ -9,7 +14,7 @@ export const avatarProps = buildProps({
|
||||
type: [Number, String],
|
||||
values: componentSizes,
|
||||
default: '',
|
||||
validator: (val: unknown): val is number => typeof val === 'number',
|
||||
validator: (val: unknown): val is number => isNumber(val),
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import type Backtop from './backtop.vue'
|
||||
|
||||
export const backtopProps = {
|
||||
visibilityHeight: {
|
||||
@ -24,3 +25,5 @@ export const backtopEmits = {
|
||||
click: (evt: MouseEvent) => evt instanceof MouseEvent,
|
||||
}
|
||||
export type BacktopEmits = typeof backtopEmits
|
||||
|
||||
export type BacktopInstance = InstanceType<typeof Backtop>
|
||||
|
@ -20,7 +20,6 @@ import { ElIcon } from '@element-plus/components/icon'
|
||||
import { easeInOutCubic, throwError } from '@element-plus/utils'
|
||||
import { CaretTop } from '@element-plus/icons-vue'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
|
||||
import { backtopEmits, backtopProps } from './backtop'
|
||||
|
||||
const COMPONENT_NAME = 'ElBacktop'
|
||||
@ -43,6 +42,8 @@ const backTopStyle = computed(() => ({
|
||||
}))
|
||||
|
||||
const scrollToTop = () => {
|
||||
// TODO: use https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo, with behavior: 'smooth'
|
||||
|
||||
if (!el.value) return
|
||||
const beginTime = Date.now()
|
||||
const beginValue = el.value.scrollTop
|
||||
@ -68,6 +69,7 @@ const handleClick = (event: MouseEvent) => {
|
||||
|
||||
const handleScrollThrottled = useThrottleFn(handleScroll, 300)
|
||||
|
||||
useEventListener(container, 'scroll', handleScrollThrottled)
|
||||
onMounted(() => {
|
||||
container.value = document
|
||||
el.value = document.documentElement
|
||||
@ -79,7 +81,5 @@ onMounted(() => {
|
||||
}
|
||||
container.value = el.value
|
||||
}
|
||||
|
||||
useEventListener(container, 'scroll', handleScrollThrottled)
|
||||
})
|
||||
</script>
|
||||
|
@ -18,14 +18,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getCurrentInstance, inject, ref } from 'vue'
|
||||
import { getCurrentInstance, inject, ref, toRefs } from 'vue'
|
||||
import ElIcon from '@element-plus/components/icon'
|
||||
import { breadcrumbKey } from '@element-plus/tokens'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { breadcrumbItemProps } from './breadcrumb-item'
|
||||
|
||||
import type { Router } from 'vue-router'
|
||||
import type { BreadcrumbProps } from './breadcrumb'
|
||||
|
||||
defineOptions({
|
||||
name: 'ElBreadcrumbItem',
|
||||
@ -34,12 +33,11 @@ defineOptions({
|
||||
const props = defineProps(breadcrumbItemProps)
|
||||
|
||||
const instance = getCurrentInstance()!
|
||||
const router = instance.appContext.config.globalProperties.$router as Router
|
||||
const breadcrumbInjection = inject(breadcrumbKey, {} as BreadcrumbProps)!
|
||||
|
||||
const breadcrumbContext = inject(breadcrumbKey, undefined)!
|
||||
const ns = useNamespace('breadcrumb')
|
||||
|
||||
const { separator, separatorIcon } = breadcrumbInjection
|
||||
const { separator, separatorIcon } = toRefs(breadcrumbContext)
|
||||
const router = instance.appContext.config.globalProperties.$router as Router
|
||||
|
||||
const link = ref<HTMLSpanElement>()
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { buildProps, definePropType } from '@element-plus/utils'
|
||||
import { UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
import {
|
||||
buildProps,
|
||||
definePropType,
|
||||
isArray,
|
||||
isDate,
|
||||
} from '@element-plus/utils'
|
||||
import { INPUT_EVENT, UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
import type Calendar from './calendar.vue'
|
||||
|
||||
@ -10,23 +15,23 @@ export type CalendarDateType =
|
||||
| 'next-year'
|
||||
| 'today'
|
||||
|
||||
const isValidRange = (range: unknown): range is [Date, Date] =>
|
||||
isArray(range) && range.length === 2 && range.every((item) => isDate(item))
|
||||
|
||||
export const calendarProps = buildProps({
|
||||
modelValue: {
|
||||
type: Date,
|
||||
},
|
||||
range: {
|
||||
type: definePropType<[Date, Date]>(Array),
|
||||
validator: (range: unknown): range is [Date, Date] =>
|
||||
Array.isArray(range) &&
|
||||
range.length === 2 &&
|
||||
range.every((item) => item instanceof Date),
|
||||
validator: isValidRange,
|
||||
},
|
||||
} as const)
|
||||
export type CalendarProps = ExtractPropTypes<typeof calendarProps>
|
||||
|
||||
export const calendarEmits = {
|
||||
[UPDATE_MODEL_EVENT]: (value: Date) => value instanceof Date,
|
||||
input: (value: Date) => value instanceof Date,
|
||||
[UPDATE_MODEL_EVENT]: (value: Date) => isDate(value),
|
||||
[INPUT_EVENT]: (value: Date) => isDate(value),
|
||||
}
|
||||
export type CalendarEmits = typeof calendarEmits
|
||||
|
||||
|
@ -49,6 +49,7 @@ import dayjs from 'dayjs'
|
||||
import { ElButton, ElButtonGroup } from '@element-plus/components/button'
|
||||
import { useLocale, useNamespace } from '@element-plus/hooks'
|
||||
import { debugWarn } from '@element-plus/utils'
|
||||
import { INPUT_EVENT, UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
import DateTable from './date-table.vue'
|
||||
import { calendarEmits, calendarProps } from './calendar'
|
||||
|
||||
@ -66,32 +67,11 @@ const props = defineProps(calendarProps)
|
||||
const emit = defineEmits(calendarEmits)
|
||||
|
||||
const ns = useNamespace('calendar')
|
||||
|
||||
const { t, lang } = useLocale()
|
||||
|
||||
const selectedDay = ref<Dayjs>()
|
||||
const now = dayjs().locale(lang.value)
|
||||
|
||||
const prevMonthDayjs = computed(() => {
|
||||
return date.value.subtract(1, 'month').date(1)
|
||||
})
|
||||
|
||||
const nextMonthDayjs = computed(() => {
|
||||
return date.value.add(1, 'month').date(1)
|
||||
})
|
||||
|
||||
const prevYearDayjs = computed(() => {
|
||||
return date.value.subtract(1, 'year').date(1)
|
||||
})
|
||||
|
||||
const nextYearDayjs = computed(() => {
|
||||
return date.value.add(1, 'year').date(1)
|
||||
})
|
||||
|
||||
const i18nDate = computed(() => {
|
||||
const pickedMonth = `el.datepicker.month${date.value.format('M')}`
|
||||
return `${date.value.year()} ${t('el.datepicker.year')} ${t(pickedMonth)}`
|
||||
})
|
||||
|
||||
const realSelectedDay = computed<Dayjs | undefined>({
|
||||
get() {
|
||||
if (!props.modelValue) return selectedDay.value
|
||||
@ -102,11 +82,36 @@ const realSelectedDay = computed<Dayjs | undefined>({
|
||||
selectedDay.value = val
|
||||
const result = val.toDate()
|
||||
|
||||
emit('input', result)
|
||||
emit('update:modelValue', result)
|
||||
emit(INPUT_EVENT, result)
|
||||
emit(UPDATE_MODEL_EVENT, result)
|
||||
},
|
||||
})
|
||||
|
||||
// if range is valid, we get a two-digit array
|
||||
const validatedRange = computed(() => {
|
||||
if (!props.range) return []
|
||||
const rangeArrDayjs = props.range.map((_) => dayjs(_).locale(lang.value))
|
||||
const [startDayjs, endDayjs] = rangeArrDayjs
|
||||
if (startDayjs.isAfter(endDayjs)) {
|
||||
debugWarn(COMPONENT_NAME, 'end time should be greater than start time')
|
||||
return []
|
||||
}
|
||||
if (startDayjs.isSame(endDayjs, 'month')) {
|
||||
// same month
|
||||
return calculateValidatedDateRange(startDayjs, endDayjs)
|
||||
} else {
|
||||
// two months
|
||||
if (startDayjs.add(1, 'month').month() !== endDayjs.month()) {
|
||||
debugWarn(
|
||||
COMPONENT_NAME,
|
||||
'start time and end time interval must not exceed two months'
|
||||
)
|
||||
return []
|
||||
}
|
||||
return calculateValidatedDateRange(startDayjs, endDayjs)
|
||||
}
|
||||
})
|
||||
|
||||
const date: ComputedRef<Dayjs> = computed(() => {
|
||||
if (!props.modelValue) {
|
||||
if (realSelectedDay.value) {
|
||||
@ -119,6 +124,15 @@ const date: ComputedRef<Dayjs> = computed(() => {
|
||||
return dayjs(props.modelValue).locale(lang.value)
|
||||
}
|
||||
})
|
||||
const prevMonthDayjs = computed(() => date.value.subtract(1, 'month').date(1))
|
||||
const nextMonthDayjs = computed(() => date.value.add(1, 'month').date(1))
|
||||
const prevYearDayjs = computed(() => date.value.subtract(1, 'year').date(1))
|
||||
const nextYearDayjs = computed(() => date.value.add(1, 'year').date(1))
|
||||
|
||||
const i18nDate = computed(() => {
|
||||
const pickedMonth = `el.datepicker.month${date.value.format('M')}`
|
||||
return `${date.value.year()} ${t('el.datepicker.year')} ${t(pickedMonth)}`
|
||||
})
|
||||
|
||||
// https://github.com/element-plus/element-plus/issues/3155
|
||||
// Calculate the validate date range according to the start and end dates
|
||||
@ -194,31 +208,6 @@ const calculateValidatedDateRange = (
|
||||
}
|
||||
}
|
||||
|
||||
// if range is valid, we get a two-digit array
|
||||
const validatedRange = computed(() => {
|
||||
if (!props.range) return []
|
||||
const rangeArrDayjs = props.range.map((_) => dayjs(_).locale(lang.value))
|
||||
const [startDayjs, endDayjs] = rangeArrDayjs
|
||||
if (startDayjs.isAfter(endDayjs)) {
|
||||
debugWarn(COMPONENT_NAME, 'end time should be greater than start time')
|
||||
return []
|
||||
}
|
||||
if (startDayjs.isSame(endDayjs, 'month')) {
|
||||
// same month
|
||||
return calculateValidatedDateRange(startDayjs, endDayjs)
|
||||
} else {
|
||||
// two months
|
||||
if (startDayjs.add(1, 'month').month() !== endDayjs.month()) {
|
||||
debugWarn(
|
||||
COMPONENT_NAME,
|
||||
'start time and end time interval must not exceed two months'
|
||||
)
|
||||
return []
|
||||
}
|
||||
return calculateValidatedDateRange(startDayjs, endDayjs)
|
||||
}
|
||||
})
|
||||
|
||||
const pickDay = (day: Dayjs) => {
|
||||
realSelectedDay.value = day
|
||||
}
|
||||
|
@ -48,11 +48,10 @@ import {
|
||||
getPrevMonthLastDays,
|
||||
toNestedArr,
|
||||
} from './date-table'
|
||||
|
||||
import type { CalendarDateCell, CalendarDateCellType } from './date-table'
|
||||
import type { Dayjs } from 'dayjs'
|
||||
|
||||
dayjs.extend(localeData)
|
||||
|
||||
defineOptions({
|
||||
name: 'DateTable',
|
||||
})
|
||||
@ -60,6 +59,8 @@ defineOptions({
|
||||
const props = defineProps(dateTableProps)
|
||||
const emit = defineEmits(dateTableEmits)
|
||||
|
||||
dayjs.extend(localeData)
|
||||
|
||||
const { t, lang } = useLocale()
|
||||
const nsTable = useNamespace('calendar-table')
|
||||
const nsDay = useNamespace('calendar-day')
|
||||
|
@ -13,6 +13,7 @@ export const cardProps = buildProps({
|
||||
},
|
||||
shadow: {
|
||||
type: String,
|
||||
values: ['always', 'hover', 'never'],
|
||||
default: 'always',
|
||||
},
|
||||
} as const)
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { buildProps, isBoolean } from '@element-plus/utils'
|
||||
import { CHANGE_EVENT } from '@element-plus/constants'
|
||||
|
||||
import type CheckTag from './check-tag.vue'
|
||||
import type { ExtractPropTypes } from 'vue'
|
||||
|
||||
@ -12,7 +14,7 @@ export type CheckTagProps = ExtractPropTypes<typeof checkTagProps>
|
||||
|
||||
export const checkTagEmits = {
|
||||
'update:checked': (value: boolean) => isBoolean(value),
|
||||
change: (value: boolean) => isBoolean(value),
|
||||
[CHANGE_EVENT]: (value: boolean) => isBoolean(value),
|
||||
}
|
||||
export type CheckTagEmits = typeof checkTagEmits
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { CHANGE_EVENT } from '@element-plus/constants'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { checkTagEmits, checkTagProps } from './check-tag'
|
||||
|
||||
@ -18,7 +19,7 @@ const ns = useNamespace('check-tag')
|
||||
|
||||
const handleChange = () => {
|
||||
const checked = !props.checked
|
||||
emit('change', checked)
|
||||
emit(CHANGE_EVENT, checked)
|
||||
emit('update:checked', checked)
|
||||
}
|
||||
</script>
|
||||
|
Loading…
Reference in New Issue
Block a user