mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
refactor(components): [segmented] make component generic
This commit is contained in:
@@ -9,7 +9,8 @@ import { useAriaProps, useSizeProp } from '@element-plus/hooks'
|
||||
import { CHANGE_EVENT, UPDATE_MODEL_EVENT } from '@element-plus/constants'
|
||||
|
||||
import type { Option } from './types'
|
||||
import type { ExtractPublicPropTypes } from 'vue'
|
||||
import type { ComponentInstance, ExtractPublicPropTypes } from 'vue'
|
||||
import type { ComponentExposed } from 'vue-component-type-helpers'
|
||||
import type { ComponentSize } from '@element-plus/constants'
|
||||
import type Segmented from './segmented.vue'
|
||||
|
||||
@@ -25,12 +26,12 @@ export const defaultProps: Required<Props> = {
|
||||
disabled: 'disabled',
|
||||
}
|
||||
|
||||
export interface SegmentedProps {
|
||||
export interface SegmentedProps<T extends Option = Option> {
|
||||
direction?: 'vertical' | 'horizontal'
|
||||
/**
|
||||
* @description options of segmented
|
||||
*/
|
||||
options?: Option[]
|
||||
options?: T[]
|
||||
/**
|
||||
* @description binding value
|
||||
*/
|
||||
@@ -144,4 +145,5 @@ export const segmentedEmits = {
|
||||
}
|
||||
export type SegmentedEmits = typeof segmentedEmits
|
||||
|
||||
export type SegmentedInstance = InstanceType<typeof Segmented> & unknown
|
||||
export type SegmentedInstance = ComponentInstance<typeof Segmented> &
|
||||
ComponentExposed<typeof Segmented>
|
||||
|
||||
@@ -24,14 +24,14 @@
|
||||
@change="handleChange($event, item)"
|
||||
/>
|
||||
<div :class="ns.e('item-label')">
|
||||
<slot :item="intoAny(item)">{{ getLabel(item) }}</slot>
|
||||
<slot :item="item">{{ getLabel(item) }}</slot>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
<script lang="ts" setup generic="T extends Option = Option">
|
||||
import { computed, reactive, ref, watch } from 'vue'
|
||||
import { useActiveElement, useResizeObserver } from '@vueuse/core'
|
||||
import { useId, useNamespace } from '@element-plus/hooks'
|
||||
@@ -52,7 +52,7 @@ defineOptions({
|
||||
name: 'ElSegmented',
|
||||
})
|
||||
|
||||
const props = withDefaults(defineProps<SegmentedProps>(), {
|
||||
const props = withDefaults(defineProps<SegmentedProps<T>>(), {
|
||||
direction: 'horizontal',
|
||||
options: () => [],
|
||||
props: () => defaultProps,
|
||||
@@ -83,7 +83,7 @@ const state = reactive({
|
||||
focusVisible: false,
|
||||
})
|
||||
|
||||
const handleChange = (evt: Event, item: Option) => {
|
||||
const handleChange = (evt: Event, item: T) => {
|
||||
const value = getValue(item)
|
||||
emit(UPDATE_MODEL_EVENT, value)
|
||||
emit(CHANGE_EVENT, value)
|
||||
@@ -92,25 +92,22 @@ const handleChange = (evt: Event, item: Option) => {
|
||||
|
||||
const aliasProps = computed(() => ({ ...defaultProps, ...props.props }))
|
||||
|
||||
//FIXME: remove this when vue >=3.3
|
||||
const intoAny = (item: any) => item
|
||||
|
||||
const getValue = (item: Option) => {
|
||||
const getValue = (item: T) => {
|
||||
return isObject(item) ? item[aliasProps.value.value] : item
|
||||
}
|
||||
|
||||
const getLabel = (item: Option) => {
|
||||
const getLabel = (item: T) => {
|
||||
return isObject(item) ? item[aliasProps.value.label] : item
|
||||
}
|
||||
|
||||
const getDisabled = (item: Option | undefined) => {
|
||||
const getDisabled = (item: T | undefined) => {
|
||||
return !!(
|
||||
_disabled.value ||
|
||||
(isObject(item) ? item[aliasProps.value.disabled] : false)
|
||||
)
|
||||
}
|
||||
|
||||
const getSelected = (item: Option) => {
|
||||
const getSelected = (item: T) => {
|
||||
return props.modelValue === getValue(item)
|
||||
}
|
||||
|
||||
@@ -118,7 +115,7 @@ const getOption = (value: any) => {
|
||||
return props.options.find((item) => getValue(item) === value)
|
||||
}
|
||||
|
||||
const getItemCls = (item: Option) => {
|
||||
const getItemCls = (item: T) => {
|
||||
return [
|
||||
ns.e('item'),
|
||||
ns.is('selected', getSelected(item)),
|
||||
|
||||
Reference in New Issue
Block a user