Files
element-plus/packages/components/select/src/useOption.ts
Delyan Haralanov c17161e21c Feat/remove mitt (#3356)
* feat(components): collapse use provide/inject instead of mitt events

# Conflicts:
#	packages/components/collapse/src/collapse-item.vue
#	packages/components/collapse/src/collapse.vue

* feat(components): menu use provide/inject instead of mitt events

# Conflicts:
#	packages/components/menu/src/menu.ts

* feat(components): form use provide/inject instead of mitt events

# Conflicts:
#	packages/components/checkbox/src/checkbox-group.vue
#	packages/components/checkbox/src/useCheckbox.ts
#	packages/components/form/src/form-item.vue
#	packages/components/form/src/form.vue
#	packages/components/input/src/index.vue
#	packages/components/radio/src/radio-group.vue
#	packages/components/select/src/useSelect.ts
#	packages/components/slider/src/index.vue
#	packages/components/time-picker/src/common/picker.vue
#	packages/components/transfer/src/index.vue
#	packages/tokens/form.ts

* feat(components): tree use provide/inject instead of mitt events

# Conflicts:
#	packages/components/tree/src/model/useDragNode.ts
#	packages/components/tree/src/tree-node.vue

* feat(components): select use provide/inject instead of mitt events

# Conflicts:
#	packages/components/select/src/option-group.vue
#	packages/components/select/src/select.vue
#	packages/components/select/src/useOption.ts
#	packages/components/select/src/useSelect.ts

* feat: remove mitt from packages dependencies

# Conflicts:
#	packages/components/package.json
#	packages/element-plus/package.json
#	packages/tokens/package.json

* feat: remove mitt from webpack.config.js

* refactor: change imports order

* refactor: import types separately

* fix: revert removing mitt from webpack.config.js

This config is not related to the build so no need to remove mitt here
2021-09-16 21:19:27 +08:00

140 lines
3.3 KiB
TypeScript

import { inject, computed, getCurrentInstance, watch, toRaw, unref } from 'vue'
import { getValueByPath, escapeRegexpString } from '@element-plus/utils/util'
import { selectKey, selectGroupKey } from './token'
import type { Ref } from 'vue'
import type { QueryChangeCtx } from './token'
export function useOption(props, states) {
// inject
const select = inject(selectKey)
const selectGroup = inject(selectGroupKey, { disabled: false })
// computed
const isObject = computed(() => {
return (
Object.prototype.toString.call(props.value).toLowerCase() ===
'[object object]'
)
})
const itemSelected = computed(() => {
if (!select.props.multiple) {
return isEqual(props.value, select.props.modelValue)
} else {
return contains(select.props.modelValue as unknown[], props.value)
}
})
const limitReached = computed(() => {
if (select.props.multiple) {
const modelValue = (select.props.modelValue || []) as unknown[]
return (
!itemSelected.value &&
modelValue.length >= select.props.multipleLimit &&
select.props.multipleLimit > 0
)
} else {
return false
}
})
const currentLabel = computed(() => {
return props.label || (isObject.value ? '' : props.value)
})
const currentValue = computed(() => {
return props.value || props.label || ''
})
const isDisabled = computed(() => {
return props.disabled || states.groupDisabled || limitReached.value
})
const instance = getCurrentInstance()
const contains = (arr = [], target) => {
if (!isObject.value) {
return arr && arr.indexOf(target) > -1
} else {
const valueKey = select.props.valueKey
return (
arr &&
arr.some((item) => {
return (
getValueByPath(item, valueKey) === getValueByPath(target, valueKey)
)
})
)
}
}
const isEqual = (a: unknown, b: unknown) => {
if (!isObject.value) {
return a === b
} else {
const { valueKey } = select.props
return getValueByPath(a, valueKey) === getValueByPath(b, valueKey)
}
}
const hoverItem = () => {
if (!props.disabled && !selectGroup.disabled) {
select.hoverIndex = select.optionsArray.indexOf(instance)
}
}
watch(
() => currentLabel.value,
() => {
if (!props.created && !select.props.remote) select.setSelected()
}
)
watch(
() => props.value,
(val, oldVal) => {
const { remote, valueKey } = select.props
if (!props.created && !remote) {
if (
valueKey &&
typeof val === 'object' &&
typeof oldVal === 'object' &&
val[valueKey] === oldVal[valueKey]
) {
return
}
select.setSelected()
}
}
)
watch(
() => selectGroup.disabled,
() => {
states.groupDisabled = selectGroup.disabled
},
{ immediate: true }
)
const { queryChange } = toRaw(select)
watch(queryChange, (changes: Ref<QueryChangeCtx>) => {
const { query } = unref(changes)
const regexp = new RegExp(escapeRegexpString(query), 'i')
states.visible = regexp.test(currentLabel.value) || props.created
if (!states.visible) {
select.filteredOptionsCount--
}
})
return {
select,
currentLabel,
currentValue,
itemSelected,
isDisabled,
hoverItem,
}
}