Skip to content

Commit

Permalink
Merge pull request #1724 from DevCloudFE/dev
Browse files Browse the repository at this point in the history
fix(select): revert refactor to fix dropdown flexable (#1723)
  • Loading branch information
GreatZPP authored Sep 1, 2023
2 parents ed9f989 + 9e88ef3 commit e50a3c8
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 339 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineComponent, provide, reactive, toRefs } from 'vue';
import type { SetupContext } from 'vue';
import { optionGroupProps, OptionGroupProps, OptionGroupContext } from '../select-types';
import { useNamespace } from '@devui/shared/utils';
import { useNamespace } from '../../../shared/hooks/use-namespace';
import { OPTION_GROUP_TOKEN } from '../const';

export default defineComponent({
Expand Down
77 changes: 20 additions & 57 deletions packages/devui-vue/devui/select/src/components/select-content.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { defineComponent, inject, computed, withModifiers } from 'vue';
import type { SetupContext } from 'vue';
import AlertCloseIcon from '../../../alert/src/components/alert-close-icon';
import SelectArrowIcon from './select-arrow-icon';
import { Tag, SizeType } from '../../../tag';
import { Popover } from '../../../popover';
import { useNamespace } from '@devui/shared/utils';
import { useNamespace } from '../../../shared/hooks/use-namespace';
import useSelectContent from '../composables/use-select-content';
import { OptionObjectItem } from '../select-types';
import { FORM_ITEM_TOKEN } from '../../../form';

export default defineComponent({
name: 'SelectContent',
setup(_, ctx: SetupContext) {
setup() {
const formItemContext = inject(FORM_ITEM_TOKEN, undefined);
const ns = useNamespace('select');
const clearCls = computed(() => ({
Expand All @@ -25,70 +24,44 @@ export default defineComponent({
const multipleCls = ns.e('multiple');
const multipleInputCls = ns.em('multiple', 'input');
const {
singleInputRef,
searchQuery,
singleSearchKey,
selectedData,
isSelectDisable,
isSupportCollapseTags,
isDisabledTooltip,
isReadOnly,
isSupportFilter,
selectionCls,
inputCls,
tagSize,
placeholder,
singlePlaceholder,
singlePlaceholderWidth,
isMultiple,
isPlaceholderDark,
displayInputValue,
onSingleInputWrapClick,
onMultipleClick,
onArrowClick,
handleClear,
tagDelete,
onFocus,
onBlur,
queryFilter,
} = useSelectContent();

const clearSingleSearchKey = () => {
singleSearchKey.value = '';
};

const clearMultipleSearchKey = () => {
searchQuery.value = '';
};

ctx.expose({
clearSingleSearchKey,
clearMultipleSearchKey,
});

return () => {
return (
<div class={selectionCls.value}>
{isMultiple.value ? (
<div class={multipleCls} onClick={onMultipleClick}>
<div class={multipleCls}>
{!isSupportCollapseTags.value &&
selectedData.value.length >= 1 &&
selectedData.value.map((item: OptionObjectItem) => (
<Tag
deletable={!(isSelectDisable.value || item.disabled)}
deletable
onTagDelete={withModifiers(() => tagDelete(item), ['prevent', 'stop'])}
key={item.value}
maxWidth={'78%'}
class={['multiple-tag', { disabled: isSelectDisable.value || item.disabled }]}
size={tagSize.value as SizeType}>
{item.name}
</Tag>
))}
{isSupportCollapseTags.value && selectedData.value.length >= 1 && (
<Tag
deletable
maxWidth={'75%'}
class={'multiple-tag'}
onTagDelete={withModifiers(() => tagDelete(selectedData.value[0]), ['prevent', 'stop'])}
size={tagSize.value as SizeType}>
{selectedData.value[0].name}
Expand All @@ -97,7 +70,6 @@ export default defineComponent({
{isSupportCollapseTags.value && selectedData.value.length > 1 && (
<Popover
trigger="hover"
auto-update-position
disabled={isDisabledTooltip.value}
v-slots={{
default: () => <Tag size={tagSize.value as SizeType}>{`+${selectedData.value.length - 1}`}</Tag>,
Expand All @@ -110,7 +82,6 @@ export default defineComponent({
deletable
onTagDelete={withModifiers(() => tagDelete(item), ['prevent', 'stop'])}
key={item.value}
class="popover-tag"
size={tagSize.value as SizeType}>
{item.name}
</Tag>
Expand All @@ -122,45 +93,37 @@ export default defineComponent({
)}
<div class={multipleInputCls}>
<input
v-show={!selectedData.value.length || isSupportFilter.value}
ref="input"
value={searchQuery.value}
type="text"
class={inputCls.value}
placeholder={placeholder.value}
readonly={isReadOnly.value || !isSupportFilter.value}
readonly={isReadOnly.value}
disabled={isSelectDisable.value}
onInput={queryFilter}
onFocus={onFocus}
onBlur={onBlur}
/>
</div>
</div>
) : (
<div class="single-inner-input" onClick={onSingleInputWrapClick}>
{!singleSearchKey.value && (
<span
class={['input-placeholder', { 'placeholder-dark': isPlaceholderDark.value }]}
style={{ width: singlePlaceholderWidth.value }}
title={displayInputValue.value || singlePlaceholder.value}>
{displayInputValue.value || singlePlaceholder.value}
</span>
)}
<input
ref={singleInputRef}
type="text"
v-model={singleSearchKey.value}
class={inputCls.value}
readonly={isReadOnly.value}
disabled={isSelectDisable.value}
onFocus={onFocus}
onBlur={onBlur}
onInput={queryFilter}
/>
</div>
<input
ref="input"
value={displayInputValue.value}
type="text"
class={inputCls.value}
placeholder={placeholder.value}
readonly={isReadOnly.value}
disabled={isSelectDisable.value}
onFocus={onFocus}
onBlur={onBlur}
onInput={queryFilter}
/>
)}
<span onClick={handleClear} class={clearCls.value}>
<AlertCloseIcon />
</span>
<span class={arrowCls.value} onClick={onArrowClick}>
<span class={arrowCls.value}>
<SelectArrowIcon />
</span>
</div>
Expand Down
9 changes: 3 additions & 6 deletions packages/devui-vue/devui/select/src/composables/use-option.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { computed, inject, onBeforeMount, onBeforeUnmount, ref } from 'vue';
import { OptionProps, UseOptionReturnType } from '../select-types';
import { SELECT_TOKEN, OPTION_GROUP_TOKEN } from '../const';
import { className } from '../utils';
import { useNamespace } from '@devui/shared/utils';
import { useNamespace } from '../../../shared/hooks/use-namespace';
export default function useOption(props: OptionProps): UseOptionReturnType {
const ns = useNamespace('select');
const select = inject(SELECT_TOKEN, null);
Expand All @@ -22,26 +22,23 @@ export default function useOption(props: OptionProps): UseOptionReturnType {
}
});

const isDisabled = computed(() => props.disabled || (optionGroup?.disabled ? true : false));

const optionItem = computed(() => {
return {
name: props.name || props.value + '' || '',
value: props.value,
create: props.create,
_checked: false,
disabled: isDisabled.value,
};
});

const isDisabled = computed(() => props.disabled || (optionGroup?.disabled ? true : false));

const isObjectOption = ref(!!props.name);

const selectOptionCls = computed(() => {
return className(ns.e('item'), {
active: isOptionSelected.value,
disabled: isDisabled.value,
[ns.em('item', 'sm')]: select?.selectSize === 'sm',
[ns.em('item', 'lg')]: select?.selectSize === 'lg',
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { computed, inject, ref, getCurrentInstance } from 'vue';
import { SELECT_TOKEN } from '../const';
import { FORM_ITEM_TOKEN, STYLE_TOKEN } from '../../../form';
import { FORM_ITEM_TOKEN } from '../../../form';
import { OptionObjectItem, UseSelectContentReturnType } from '../select-types';
import { useNamespace } from '@devui/shared/utils';
import { useNamespace } from '../../../shared/hooks/use-namespace';
import { className } from '../utils';
import { isFunction } from 'lodash';
import { createI18nTranslate } from '../../../locale/create';
Expand All @@ -11,17 +11,11 @@ export default function useSelectContent(): UseSelectContentReturnType {
const ns = useNamespace('select');
const select = inject(SELECT_TOKEN);
const formItemContext = inject(FORM_ITEM_TOKEN, undefined);
const styleType = inject(STYLE_TOKEN, undefined);

const app = getCurrentInstance();
const t = createI18nTranslate('DSelect', app);

const searchQuery = ref('');
const singleSearchKey = ref('');
const singleInputRef = ref();

const singlePlaceholderWidth = computed(() => (select?.dropdownWidth ? `${select?.dropdownWidth - 40}px` : 'auto'));

const selectedData = computed<OptionObjectItem[]>(() => {
return select?.selectedOptions || [];
});
Expand All @@ -42,27 +36,12 @@ export default function useSelectContent(): UseSelectContentReturnType {
if (select?.selectedOptions) {
return select.selectedOptions.length > 1
? select.selectedOptions.map((item) => item?.name || item?.value || '').join(',')
: select.selectedOptions[0]?.name || (select.showEmptyWhenUnmatched ? '' : select.modelValue);
: select.selectedOptions[0]?.name || '';
} else {
return '';
}
});

const isPlaceholderDark = computed(() => {
if (!singleSearchKey.value) {
if (isSelectDisable.value) {
return false;
}
if (!displayInputValue.value) {
return true;
} else {
return select?.isSelectFocus;
}
} else {
return false;
}
});

// 是否可清空
const mergeClearable = computed<boolean>(() => {
return !isSelectDisable.value && !!select?.allowClear && (displayInputValue.value ? true : false);
Expand All @@ -73,13 +52,10 @@ export default function useSelectContent(): UseSelectContentReturnType {
return !isSupportTagsTooltip.value || !!select?.isOpen;
});

const isSupportFilter = computed(() => isFunction(select?.filter) || (typeof select?.filter === 'boolean' && select?.filter));

const selectionCls = computed(() => {
return className(ns.e('selection'), {
[ns.e('clearable')]: mergeClearable.value,
[ns.em('selection', 'error')]: isValidateError.value,
[ns.em('selection', 'gray-style')]: styleType === 'gray',
});
});

Expand All @@ -94,24 +70,14 @@ export default function useSelectContent(): UseSelectContentReturnType {

const placeholder = computed<string>(() => (displayInputValue.value ? '' : select?.placeholder || t('placeholder')));

const singlePlaceholder = computed<string>(() => select?.placeholder || t('placeholder'));

const isMultiple = computed<boolean>(() => !!select?.multiple);

const handleClear = (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
searchQuery.value = '';
singleSearchKey.value = '';
select?.handleClear();
};

const onSingleInputWrapClick = () => {
if (!select?.selectDisabled) {
singleInputRef.value.focus();
}
};

const tagDelete = (data: OptionObjectItem) => {
if (data && (data.value || data.value === 0)) {
select?.tagDelete(data);
Expand All @@ -123,65 +89,35 @@ export default function useSelectContent(): UseSelectContentReturnType {
};

const onBlur = (e: FocusEvent) => {
singleSearchKey.value = '';
select?.onBlur(e);
};

const onMultipleClick = () => {
if (select?.selectDisabled) {
return;
}
if (select?.isOpen) {
searchQuery.value = '';
select?.onBlur();
} else {
select?.onFocus();
}
};

const onArrowClick = () => {
if (isMultiple.value) {
onMultipleClick();
}
};

const queryFilter = (e: Event) => {
e.preventDefault();
e.stopPropagation();
const query = (e.target as HTMLInputElement).value;
singleSearchKey.value = query;
searchQuery.value = query;
if (!isReadOnly.value && select?.debounceQueryFilter) {
select?.debounceQueryFilter(query);
}
};

return {
singleInputRef,
searchQuery,
singleSearchKey,
selectedData,
isSelectDisable,
isSupportCollapseTags,
isDisabledTooltip,
isSupportFilter,
isReadOnly,
selectionCls,
inputCls,
tagSize,
placeholder,
singlePlaceholder,
singlePlaceholderWidth,
isMultiple,
displayInputValue,
isPlaceholderDark,
onSingleInputWrapClick,
handleClear,
tagDelete,
onFocus,
onBlur,
onMultipleClick,
onArrowClick,
queryFilter,
};
}
Loading

0 comments on commit e50a3c8

Please sign in to comment.