807 lines
27 KiB
JavaScript
807 lines
27 KiB
JavaScript
import { Fragment, computed, defineComponent, h, nextTick, onMounted, ref, toRef, watch, watchEffect } from 'vue';
|
|
import { VOverflow } from 'vueuc';
|
|
import { getPadding } from 'seemly';
|
|
import { NPopover } from "../../../popover/index.mjs";
|
|
import { NTag } from "../../../tag/index.mjs";
|
|
import { useConfig, useRtl, useTheme, useThemeClass } from "../../../_mixins/index.mjs";
|
|
import { Wrapper, createKey, getTitleAttribute, render, useOnResize } from "../../../_utils/index.mjs";
|
|
import Suffix from "../../suffix/index.mjs";
|
|
import { internalSelectionLight } from "../styles/index.mjs";
|
|
import style from "./styles/index.cssr.mjs";
|
|
export default defineComponent({
|
|
name: 'InternalSelection',
|
|
props: Object.assign(Object.assign({}, useTheme.props), {
|
|
clsPrefix: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
bordered: {
|
|
type: Boolean,
|
|
default: undefined
|
|
},
|
|
active: Boolean,
|
|
pattern: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
placeholder: String,
|
|
selectedOption: {
|
|
type: Object,
|
|
default: null
|
|
},
|
|
selectedOptions: {
|
|
type: Array,
|
|
default: null
|
|
},
|
|
labelField: {
|
|
type: String,
|
|
default: 'label'
|
|
},
|
|
valueField: {
|
|
type: String,
|
|
default: 'value'
|
|
},
|
|
multiple: Boolean,
|
|
filterable: Boolean,
|
|
clearable: Boolean,
|
|
disabled: Boolean,
|
|
size: {
|
|
type: String,
|
|
default: 'medium'
|
|
},
|
|
loading: Boolean,
|
|
autofocus: Boolean,
|
|
showArrow: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
inputProps: Object,
|
|
focused: Boolean,
|
|
renderTag: Function,
|
|
onKeydown: Function,
|
|
onClick: Function,
|
|
onBlur: Function,
|
|
onFocus: Function,
|
|
onDeleteOption: Function,
|
|
maxTagCount: [String, Number],
|
|
ellipsisTagPopoverProps: Object,
|
|
onClear: Function,
|
|
onPatternInput: Function,
|
|
onPatternFocus: Function,
|
|
onPatternBlur: Function,
|
|
renderLabel: Function,
|
|
status: String,
|
|
inlineThemeDisabled: Boolean,
|
|
ignoreComposition: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
onResize: Function
|
|
}),
|
|
setup(props) {
|
|
const {
|
|
mergedClsPrefixRef,
|
|
mergedRtlRef
|
|
} = useConfig(props);
|
|
const rtlEnabledRef = useRtl('InternalSelection', mergedRtlRef, mergedClsPrefixRef);
|
|
const patternInputMirrorRef = ref(null);
|
|
const patternInputRef = ref(null);
|
|
const selfRef = ref(null);
|
|
const multipleElRef = ref(null);
|
|
const singleElRef = ref(null);
|
|
const patternInputWrapperRef = ref(null);
|
|
const counterRef = ref(null);
|
|
const counterWrapperRef = ref(null);
|
|
const overflowRef = ref(null);
|
|
const inputTagElRef = ref(null);
|
|
const showTagsPopoverRef = ref(false);
|
|
const patternInputFocusedRef = ref(false);
|
|
const hoverRef = ref(false);
|
|
const themeRef = useTheme('InternalSelection', '-internal-selection', style, internalSelectionLight, props, toRef(props, 'clsPrefix'));
|
|
const mergedClearableRef = computed(() => {
|
|
return props.clearable && !props.disabled && (hoverRef.value || props.active);
|
|
});
|
|
const filterablePlaceholderRef = computed(() => {
|
|
return props.selectedOption ? props.renderTag ? props.renderTag({
|
|
option: props.selectedOption,
|
|
handleClose: () => {}
|
|
}) : props.renderLabel ? props.renderLabel(props.selectedOption, true) : render(props.selectedOption[props.labelField], props.selectedOption, true) : props.placeholder;
|
|
});
|
|
const labelRef = computed(() => {
|
|
const option = props.selectedOption;
|
|
if (!option) return undefined;
|
|
return option[props.labelField];
|
|
});
|
|
const selectedRef = computed(() => {
|
|
if (props.multiple) {
|
|
return !!(Array.isArray(props.selectedOptions) && props.selectedOptions.length);
|
|
} else {
|
|
return props.selectedOption !== null;
|
|
}
|
|
});
|
|
function syncMirrorWidth() {
|
|
var _a;
|
|
const {
|
|
value: patternInputMirrorEl
|
|
} = patternInputMirrorRef;
|
|
if (patternInputMirrorEl) {
|
|
const {
|
|
value: patternInputEl
|
|
} = patternInputRef;
|
|
if (patternInputEl) {
|
|
patternInputEl.style.width = `${patternInputMirrorEl.offsetWidth}px`;
|
|
if (props.maxTagCount !== 'responsive') {
|
|
(_a = overflowRef.value) === null || _a === void 0 ? void 0 : _a.sync({
|
|
showAllItemsBeforeCalculate: false
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
function hideInputTag() {
|
|
const {
|
|
value: inputTagEl
|
|
} = inputTagElRef;
|
|
if (inputTagEl) inputTagEl.style.display = 'none';
|
|
}
|
|
function showInputTag() {
|
|
const {
|
|
value: inputTagEl
|
|
} = inputTagElRef;
|
|
if (inputTagEl) inputTagEl.style.display = 'inline-block';
|
|
}
|
|
watch(toRef(props, 'active'), value => {
|
|
if (!value) hideInputTag();
|
|
});
|
|
watch(toRef(props, 'pattern'), () => {
|
|
if (props.multiple) {
|
|
void nextTick(syncMirrorWidth);
|
|
}
|
|
});
|
|
function doFocus(e) {
|
|
const {
|
|
onFocus
|
|
} = props;
|
|
if (onFocus) onFocus(e);
|
|
}
|
|
function doBlur(e) {
|
|
const {
|
|
onBlur
|
|
} = props;
|
|
if (onBlur) onBlur(e);
|
|
}
|
|
function doDeleteOption(value) {
|
|
const {
|
|
onDeleteOption
|
|
} = props;
|
|
if (onDeleteOption) onDeleteOption(value);
|
|
}
|
|
function doClear(e) {
|
|
const {
|
|
onClear
|
|
} = props;
|
|
if (onClear) onClear(e);
|
|
}
|
|
function doPatternInput(value) {
|
|
const {
|
|
onPatternInput
|
|
} = props;
|
|
if (onPatternInput) onPatternInput(value);
|
|
}
|
|
function handleFocusin(e) {
|
|
var _a;
|
|
if (!e.relatedTarget || !((_a = selfRef.value) === null || _a === void 0 ? void 0 : _a.contains(e.relatedTarget))) {
|
|
doFocus(e);
|
|
}
|
|
}
|
|
function handleFocusout(e) {
|
|
var _a;
|
|
if ((_a = selfRef.value) === null || _a === void 0 ? void 0 : _a.contains(e.relatedTarget)) return;
|
|
doBlur(e);
|
|
}
|
|
function handleClear(e) {
|
|
doClear(e);
|
|
}
|
|
function handleMouseEnter() {
|
|
hoverRef.value = true;
|
|
}
|
|
function handleMouseLeave() {
|
|
hoverRef.value = false;
|
|
}
|
|
function handleMouseDown(e) {
|
|
if (!props.active || !props.filterable) return;
|
|
if (e.target === patternInputRef.value) return;
|
|
e.preventDefault();
|
|
}
|
|
function handleDeleteOption(option) {
|
|
doDeleteOption(option);
|
|
}
|
|
const isComposingRef = ref(false);
|
|
function handlePatternKeyDown(e) {
|
|
if (e.key === 'Backspace' && !isComposingRef.value) {
|
|
if (!props.pattern.length) {
|
|
const {
|
|
selectedOptions
|
|
} = props;
|
|
if (selectedOptions === null || selectedOptions === void 0 ? void 0 : selectedOptions.length) {
|
|
handleDeleteOption(selectedOptions[selectedOptions.length - 1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// the composition end is later than its input so we can cached the event
|
|
// and return the input event
|
|
let cachedInputEvent = null;
|
|
function handlePatternInputInput(e) {
|
|
// we should sync mirror width here
|
|
const {
|
|
value: patternInputMirrorEl
|
|
} = patternInputMirrorRef;
|
|
if (patternInputMirrorEl) {
|
|
const inputText = e.target.value;
|
|
patternInputMirrorEl.textContent = inputText;
|
|
syncMirrorWidth();
|
|
}
|
|
if (props.ignoreComposition) {
|
|
if (!isComposingRef.value) {
|
|
doPatternInput(e);
|
|
} else {
|
|
cachedInputEvent = e;
|
|
}
|
|
} else {
|
|
doPatternInput(e);
|
|
}
|
|
}
|
|
function handleCompositionStart() {
|
|
isComposingRef.value = true;
|
|
}
|
|
function handleCompositionEnd() {
|
|
isComposingRef.value = false;
|
|
if (props.ignoreComposition) {
|
|
doPatternInput(cachedInputEvent);
|
|
}
|
|
cachedInputEvent = null;
|
|
}
|
|
function handlePatternInputFocus(e) {
|
|
var _a;
|
|
patternInputFocusedRef.value = true;
|
|
(_a = props.onPatternFocus) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
}
|
|
function handlePatternInputBlur(e) {
|
|
var _a;
|
|
patternInputFocusedRef.value = false;
|
|
(_a = props.onPatternBlur) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
}
|
|
function blur() {
|
|
var _a, _b;
|
|
if (props.filterable) {
|
|
patternInputFocusedRef.value = false;
|
|
(_a = patternInputWrapperRef.value) === null || _a === void 0 ? void 0 : _a.blur();
|
|
(_b = patternInputRef.value) === null || _b === void 0 ? void 0 : _b.blur();
|
|
} else if (props.multiple) {
|
|
const {
|
|
value: multipleEl
|
|
} = multipleElRef;
|
|
multipleEl === null || multipleEl === void 0 ? void 0 : multipleEl.blur();
|
|
} else {
|
|
const {
|
|
value: singleEl
|
|
} = singleElRef;
|
|
singleEl === null || singleEl === void 0 ? void 0 : singleEl.blur();
|
|
}
|
|
}
|
|
function focus() {
|
|
var _a, _b, _c;
|
|
if (props.filterable) {
|
|
patternInputFocusedRef.value = false;
|
|
(_a = patternInputWrapperRef.value) === null || _a === void 0 ? void 0 : _a.focus();
|
|
} else if (props.multiple) {
|
|
(_b = multipleElRef.value) === null || _b === void 0 ? void 0 : _b.focus();
|
|
} else {
|
|
(_c = singleElRef.value) === null || _c === void 0 ? void 0 : _c.focus();
|
|
}
|
|
}
|
|
function focusInput() {
|
|
const {
|
|
value: patternInputEl
|
|
} = patternInputRef;
|
|
if (patternInputEl) {
|
|
showInputTag();
|
|
patternInputEl.focus();
|
|
}
|
|
}
|
|
function blurInput() {
|
|
const {
|
|
value: patternInputEl
|
|
} = patternInputRef;
|
|
if (patternInputEl) {
|
|
patternInputEl.blur();
|
|
}
|
|
}
|
|
function updateCounter(count) {
|
|
const {
|
|
value
|
|
} = counterRef;
|
|
if (value) {
|
|
value.setTextContent(`+${count}`);
|
|
}
|
|
}
|
|
function getCounter() {
|
|
const {
|
|
value
|
|
} = counterWrapperRef;
|
|
return value;
|
|
}
|
|
function getTail() {
|
|
return patternInputRef.value;
|
|
}
|
|
let enterTimerId = null;
|
|
function clearEnterTimer() {
|
|
if (enterTimerId !== null) window.clearTimeout(enterTimerId);
|
|
}
|
|
function handleMouseEnterCounter() {
|
|
if (props.active) return;
|
|
clearEnterTimer();
|
|
enterTimerId = window.setTimeout(() => {
|
|
if (selectedRef.value) {
|
|
showTagsPopoverRef.value = true;
|
|
}
|
|
}, 100);
|
|
}
|
|
function handleMouseLeaveCounter() {
|
|
clearEnterTimer();
|
|
}
|
|
function onPopoverUpdateShow(show) {
|
|
if (!show) {
|
|
clearEnterTimer();
|
|
showTagsPopoverRef.value = false;
|
|
}
|
|
}
|
|
watch(selectedRef, value => {
|
|
if (!value) {
|
|
showTagsPopoverRef.value = false;
|
|
}
|
|
});
|
|
onMounted(() => {
|
|
watchEffect(() => {
|
|
const patternInputWrapperEl = patternInputWrapperRef.value;
|
|
if (!patternInputWrapperEl) return;
|
|
if (props.disabled) {
|
|
patternInputWrapperEl.removeAttribute('tabindex');
|
|
} else {
|
|
patternInputWrapperEl.tabIndex = patternInputFocusedRef.value ? -1 : 0;
|
|
}
|
|
});
|
|
});
|
|
useOnResize(selfRef, props.onResize);
|
|
const {
|
|
inlineThemeDisabled
|
|
} = props;
|
|
const cssVarsRef = computed(() => {
|
|
const {
|
|
size
|
|
} = props;
|
|
const {
|
|
common: {
|
|
cubicBezierEaseInOut
|
|
},
|
|
self: {
|
|
borderRadius,
|
|
color,
|
|
placeholderColor,
|
|
textColor,
|
|
paddingSingle,
|
|
paddingMultiple,
|
|
caretColor,
|
|
colorDisabled,
|
|
textColorDisabled,
|
|
placeholderColorDisabled,
|
|
colorActive,
|
|
boxShadowFocus,
|
|
boxShadowActive,
|
|
boxShadowHover,
|
|
border,
|
|
borderFocus,
|
|
borderHover,
|
|
borderActive,
|
|
arrowColor,
|
|
arrowColorDisabled,
|
|
loadingColor,
|
|
// form warning
|
|
colorActiveWarning,
|
|
boxShadowFocusWarning,
|
|
boxShadowActiveWarning,
|
|
boxShadowHoverWarning,
|
|
borderWarning,
|
|
borderFocusWarning,
|
|
borderHoverWarning,
|
|
borderActiveWarning,
|
|
// form error
|
|
colorActiveError,
|
|
boxShadowFocusError,
|
|
boxShadowActiveError,
|
|
boxShadowHoverError,
|
|
borderError,
|
|
borderFocusError,
|
|
borderHoverError,
|
|
borderActiveError,
|
|
// clear
|
|
clearColor,
|
|
clearColorHover,
|
|
clearColorPressed,
|
|
clearSize,
|
|
// arrow
|
|
arrowSize,
|
|
[createKey('height', size)]: height,
|
|
[createKey('fontSize', size)]: fontSize
|
|
}
|
|
} = themeRef.value;
|
|
const paddingSingleDiscrete = getPadding(paddingSingle);
|
|
const paddingMultipleDiscrete = getPadding(paddingMultiple);
|
|
return {
|
|
'--n-bezier': cubicBezierEaseInOut,
|
|
'--n-border': border,
|
|
'--n-border-active': borderActive,
|
|
'--n-border-focus': borderFocus,
|
|
'--n-border-hover': borderHover,
|
|
'--n-border-radius': borderRadius,
|
|
'--n-box-shadow-active': boxShadowActive,
|
|
'--n-box-shadow-focus': boxShadowFocus,
|
|
'--n-box-shadow-hover': boxShadowHover,
|
|
'--n-caret-color': caretColor,
|
|
'--n-color': color,
|
|
'--n-color-active': colorActive,
|
|
'--n-color-disabled': colorDisabled,
|
|
'--n-font-size': fontSize,
|
|
'--n-height': height,
|
|
'--n-padding-single-top': paddingSingleDiscrete.top,
|
|
'--n-padding-multiple-top': paddingMultipleDiscrete.top,
|
|
'--n-padding-single-right': paddingSingleDiscrete.right,
|
|
'--n-padding-multiple-right': paddingMultipleDiscrete.right,
|
|
'--n-padding-single-left': paddingSingleDiscrete.left,
|
|
'--n-padding-multiple-left': paddingMultipleDiscrete.left,
|
|
'--n-padding-single-bottom': paddingSingleDiscrete.bottom,
|
|
'--n-padding-multiple-bottom': paddingMultipleDiscrete.bottom,
|
|
'--n-placeholder-color': placeholderColor,
|
|
'--n-placeholder-color-disabled': placeholderColorDisabled,
|
|
'--n-text-color': textColor,
|
|
'--n-text-color-disabled': textColorDisabled,
|
|
'--n-arrow-color': arrowColor,
|
|
'--n-arrow-color-disabled': arrowColorDisabled,
|
|
'--n-loading-color': loadingColor,
|
|
// form warning
|
|
'--n-color-active-warning': colorActiveWarning,
|
|
'--n-box-shadow-focus-warning': boxShadowFocusWarning,
|
|
'--n-box-shadow-active-warning': boxShadowActiveWarning,
|
|
'--n-box-shadow-hover-warning': boxShadowHoverWarning,
|
|
'--n-border-warning': borderWarning,
|
|
'--n-border-focus-warning': borderFocusWarning,
|
|
'--n-border-hover-warning': borderHoverWarning,
|
|
'--n-border-active-warning': borderActiveWarning,
|
|
// form error
|
|
'--n-color-active-error': colorActiveError,
|
|
'--n-box-shadow-focus-error': boxShadowFocusError,
|
|
'--n-box-shadow-active-error': boxShadowActiveError,
|
|
'--n-box-shadow-hover-error': boxShadowHoverError,
|
|
'--n-border-error': borderError,
|
|
'--n-border-focus-error': borderFocusError,
|
|
'--n-border-hover-error': borderHoverError,
|
|
'--n-border-active-error': borderActiveError,
|
|
// clear
|
|
'--n-clear-size': clearSize,
|
|
'--n-clear-color': clearColor,
|
|
'--n-clear-color-hover': clearColorHover,
|
|
'--n-clear-color-pressed': clearColorPressed,
|
|
// arrow-size
|
|
'--n-arrow-size': arrowSize
|
|
};
|
|
});
|
|
const themeClassHandle = inlineThemeDisabled ? useThemeClass('internal-selection', computed(() => {
|
|
return props.size[0];
|
|
}), cssVarsRef, props) : undefined;
|
|
return {
|
|
mergedTheme: themeRef,
|
|
mergedClearable: mergedClearableRef,
|
|
mergedClsPrefix: mergedClsPrefixRef,
|
|
rtlEnabled: rtlEnabledRef,
|
|
patternInputFocused: patternInputFocusedRef,
|
|
filterablePlaceholder: filterablePlaceholderRef,
|
|
label: labelRef,
|
|
selected: selectedRef,
|
|
showTagsPanel: showTagsPopoverRef,
|
|
isComposing: isComposingRef,
|
|
// dom ref
|
|
counterRef,
|
|
counterWrapperRef,
|
|
patternInputMirrorRef,
|
|
patternInputRef,
|
|
selfRef,
|
|
multipleElRef,
|
|
singleElRef,
|
|
patternInputWrapperRef,
|
|
overflowRef,
|
|
inputTagElRef,
|
|
handleMouseDown,
|
|
handleFocusin,
|
|
handleClear,
|
|
handleMouseEnter,
|
|
handleMouseLeave,
|
|
handleDeleteOption,
|
|
handlePatternKeyDown,
|
|
handlePatternInputInput,
|
|
handlePatternInputBlur,
|
|
handlePatternInputFocus,
|
|
handleMouseEnterCounter,
|
|
handleMouseLeaveCounter,
|
|
handleFocusout,
|
|
handleCompositionEnd,
|
|
handleCompositionStart,
|
|
onPopoverUpdateShow,
|
|
focus,
|
|
focusInput,
|
|
blur,
|
|
blurInput,
|
|
updateCounter,
|
|
getCounter,
|
|
getTail,
|
|
renderLabel: props.renderLabel,
|
|
cssVars: inlineThemeDisabled ? undefined : cssVarsRef,
|
|
themeClass: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.themeClass,
|
|
onRender: themeClassHandle === null || themeClassHandle === void 0 ? void 0 : themeClassHandle.onRender
|
|
};
|
|
},
|
|
render() {
|
|
const {
|
|
status,
|
|
multiple,
|
|
size,
|
|
disabled,
|
|
filterable,
|
|
maxTagCount,
|
|
bordered,
|
|
clsPrefix,
|
|
ellipsisTagPopoverProps,
|
|
onRender,
|
|
renderTag,
|
|
renderLabel
|
|
} = this;
|
|
onRender === null || onRender === void 0 ? void 0 : onRender();
|
|
const maxTagCountResponsive = maxTagCount === 'responsive';
|
|
const maxTagCountNumeric = typeof maxTagCount === 'number';
|
|
const useMaxTagCount = maxTagCountResponsive || maxTagCountNumeric;
|
|
const suffix = h(Wrapper, null, {
|
|
default: () => h(Suffix, {
|
|
clsPrefix: clsPrefix,
|
|
loading: this.loading,
|
|
showArrow: this.showArrow,
|
|
showClear: this.mergedClearable && this.selected,
|
|
onClear: this.handleClear
|
|
}, {
|
|
default: () => {
|
|
var _a, _b;
|
|
return (_b = (_a = this.$slots).arrow) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
}
|
|
})
|
|
});
|
|
let body;
|
|
if (multiple) {
|
|
const {
|
|
labelField
|
|
} = this;
|
|
const createTag = option => h("div", {
|
|
class: `${clsPrefix}-base-selection-tag-wrapper`,
|
|
key: option.value
|
|
}, renderTag ? renderTag({
|
|
option,
|
|
handleClose: () => {
|
|
this.handleDeleteOption(option);
|
|
}
|
|
}) : h(NTag, {
|
|
size: size,
|
|
closable: !option.disabled,
|
|
disabled: disabled,
|
|
onClose: () => {
|
|
this.handleDeleteOption(option);
|
|
},
|
|
internalCloseIsButtonTag: false,
|
|
internalCloseFocusable: false
|
|
}, {
|
|
default: () => renderLabel ? renderLabel(option, true) : render(option[labelField], option, true)
|
|
}));
|
|
const createOriginalTagNodes = () => (maxTagCountNumeric ? this.selectedOptions.slice(0, maxTagCount) : this.selectedOptions).map(createTag);
|
|
const input = filterable ? h("div", {
|
|
class: `${clsPrefix}-base-selection-input-tag`,
|
|
ref: "inputTagElRef",
|
|
key: "__input-tag__"
|
|
}, h("input", Object.assign({}, this.inputProps, {
|
|
ref: "patternInputRef",
|
|
tabindex: -1,
|
|
disabled: disabled,
|
|
value: this.pattern,
|
|
autofocus: this.autofocus,
|
|
class: `${clsPrefix}-base-selection-input-tag__input`,
|
|
onBlur: this.handlePatternInputBlur,
|
|
onFocus: this.handlePatternInputFocus,
|
|
onKeydown: this.handlePatternKeyDown,
|
|
onInput: this.handlePatternInputInput,
|
|
onCompositionstart: this.handleCompositionStart,
|
|
onCompositionend: this.handleCompositionEnd
|
|
})), h("span", {
|
|
ref: "patternInputMirrorRef",
|
|
class: `${clsPrefix}-base-selection-input-tag__mirror`
|
|
}, this.pattern)) : null;
|
|
// May Overflow
|
|
const renderCounter = maxTagCountResponsive ? () => h("div", {
|
|
class: `${clsPrefix}-base-selection-tag-wrapper`,
|
|
ref: "counterWrapperRef"
|
|
}, h(NTag, {
|
|
size: size,
|
|
ref: "counterRef",
|
|
onMouseenter: this.handleMouseEnterCounter,
|
|
onMouseleave: this.handleMouseLeaveCounter,
|
|
disabled: disabled
|
|
})) : undefined;
|
|
let counter;
|
|
if (maxTagCountNumeric) {
|
|
const rest = this.selectedOptions.length - maxTagCount;
|
|
if (rest > 0) {
|
|
counter = h("div", {
|
|
class: `${clsPrefix}-base-selection-tag-wrapper`,
|
|
key: "__counter__"
|
|
}, h(NTag, {
|
|
size: size,
|
|
ref: "counterRef",
|
|
onMouseenter: this.handleMouseEnterCounter,
|
|
disabled: disabled
|
|
}, {
|
|
default: () => `+${rest}`
|
|
}));
|
|
}
|
|
}
|
|
const tags = maxTagCountResponsive ? filterable ? h(VOverflow, {
|
|
ref: "overflowRef",
|
|
updateCounter: this.updateCounter,
|
|
getCounter: this.getCounter,
|
|
getTail: this.getTail,
|
|
style: {
|
|
width: '100%',
|
|
display: 'flex',
|
|
overflow: 'hidden'
|
|
}
|
|
}, {
|
|
default: createOriginalTagNodes,
|
|
counter: renderCounter,
|
|
tail: () => input
|
|
}) : h(VOverflow, {
|
|
ref: "overflowRef",
|
|
updateCounter: this.updateCounter,
|
|
getCounter: this.getCounter,
|
|
style: {
|
|
width: '100%',
|
|
display: 'flex',
|
|
overflow: 'hidden'
|
|
}
|
|
}, {
|
|
default: createOriginalTagNodes,
|
|
counter: renderCounter
|
|
}) : maxTagCountNumeric && counter ? createOriginalTagNodes().concat(counter) : createOriginalTagNodes();
|
|
const renderPopover = useMaxTagCount ? () => h("div", {
|
|
class: `${clsPrefix}-base-selection-popover`
|
|
}, maxTagCountResponsive ? createOriginalTagNodes() : this.selectedOptions.map(createTag)) : undefined;
|
|
const popoverProps = useMaxTagCount ? Object.assign({
|
|
show: this.showTagsPanel,
|
|
trigger: 'hover',
|
|
overlap: true,
|
|
placement: 'top',
|
|
width: 'trigger',
|
|
onUpdateShow: this.onPopoverUpdateShow,
|
|
theme: this.mergedTheme.peers.Popover,
|
|
themeOverrides: this.mergedTheme.peerOverrides.Popover
|
|
}, ellipsisTagPopoverProps) : null;
|
|
const showPlaceholder = this.selected ? false : this.active ? !this.pattern && !this.isComposing : true;
|
|
const placeholder = showPlaceholder ? h("div", {
|
|
class: `${clsPrefix}-base-selection-placeholder ${clsPrefix}-base-selection-overlay`
|
|
}, h("div", {
|
|
class: `${clsPrefix}-base-selection-placeholder__inner`
|
|
}, this.placeholder)) : null;
|
|
const popoverTrigger = filterable ? h("div", {
|
|
ref: "patternInputWrapperRef",
|
|
class: `${clsPrefix}-base-selection-tags`
|
|
}, tags, maxTagCountResponsive ? null : input, suffix) : h("div", {
|
|
ref: "multipleElRef",
|
|
class: `${clsPrefix}-base-selection-tags`,
|
|
tabindex: disabled ? undefined : 0
|
|
}, tags, suffix);
|
|
body = h(Fragment, null, useMaxTagCount ? h(NPopover, Object.assign({}, popoverProps, {
|
|
scrollable: true,
|
|
style: "max-height: calc(var(--v-target-height) * 6.6);"
|
|
}), {
|
|
trigger: () => popoverTrigger,
|
|
default: renderPopover
|
|
}) : popoverTrigger, placeholder);
|
|
} else {
|
|
if (filterable) {
|
|
const hasInput = this.pattern || this.isComposing;
|
|
const showPlaceholder = this.active ? !hasInput : !this.selected;
|
|
const showSelectedLabel = this.active ? false : this.selected;
|
|
body = h("div", {
|
|
ref: "patternInputWrapperRef",
|
|
class: `${clsPrefix}-base-selection-label`,
|
|
title: this.patternInputFocused ? undefined : getTitleAttribute(this.label)
|
|
}, h("input", Object.assign({}, this.inputProps, {
|
|
ref: "patternInputRef",
|
|
class: `${clsPrefix}-base-selection-input`,
|
|
value: this.active ? this.pattern : '',
|
|
placeholder: "",
|
|
readonly: disabled,
|
|
disabled: disabled,
|
|
tabindex: -1,
|
|
autofocus: this.autofocus,
|
|
onFocus: this.handlePatternInputFocus,
|
|
onBlur: this.handlePatternInputBlur,
|
|
onInput: this.handlePatternInputInput,
|
|
onCompositionstart: this.handleCompositionStart,
|
|
onCompositionend: this.handleCompositionEnd
|
|
})), showSelectedLabel ? h("div", {
|
|
class: `${clsPrefix}-base-selection-label__render-label ${clsPrefix}-base-selection-overlay`,
|
|
key: "input"
|
|
}, h("div", {
|
|
class: `${clsPrefix}-base-selection-overlay__wrapper`
|
|
}, renderTag ? renderTag({
|
|
option: this.selectedOption,
|
|
handleClose: () => {}
|
|
}) : renderLabel ? renderLabel(this.selectedOption, true) : render(this.label, this.selectedOption, true))) : null, showPlaceholder ? h("div", {
|
|
class: `${clsPrefix}-base-selection-placeholder ${clsPrefix}-base-selection-overlay`,
|
|
key: "placeholder"
|
|
}, h("div", {
|
|
class: `${clsPrefix}-base-selection-overlay__wrapper`
|
|
}, this.filterablePlaceholder)) : null, suffix);
|
|
} else {
|
|
body = h("div", {
|
|
ref: "singleElRef",
|
|
class: `${clsPrefix}-base-selection-label`,
|
|
tabindex: this.disabled ? undefined : 0
|
|
}, this.label !== undefined ? h("div", {
|
|
class: `${clsPrefix}-base-selection-input`,
|
|
title: getTitleAttribute(this.label),
|
|
key: "input"
|
|
}, h("div", {
|
|
class: `${clsPrefix}-base-selection-input__content`
|
|
}, renderTag ? renderTag({
|
|
option: this.selectedOption,
|
|
handleClose: () => {}
|
|
}) : renderLabel ? renderLabel(this.selectedOption, true) : render(this.label, this.selectedOption, true))) : h("div", {
|
|
class: `${clsPrefix}-base-selection-placeholder ${clsPrefix}-base-selection-overlay`,
|
|
key: "placeholder"
|
|
}, h("div", {
|
|
class: `${clsPrefix}-base-selection-placeholder__inner`
|
|
}, this.placeholder)), suffix);
|
|
}
|
|
}
|
|
return h("div", {
|
|
ref: "selfRef",
|
|
class: [`${clsPrefix}-base-selection`, this.rtlEnabled && `${clsPrefix}-base-selection--rtl`, this.themeClass, status && `${clsPrefix}-base-selection--${status}-status`, {
|
|
[`${clsPrefix}-base-selection--active`]: this.active,
|
|
[`${clsPrefix}-base-selection--selected`]: this.selected || this.active && this.pattern,
|
|
[`${clsPrefix}-base-selection--disabled`]: this.disabled,
|
|
[`${clsPrefix}-base-selection--multiple`]: this.multiple,
|
|
// focus is not controlled by selection itself since it always need
|
|
// to be managed together with menu. provide :focus style will cause
|
|
// many redundant codes.
|
|
[`${clsPrefix}-base-selection--focus`]: this.focused
|
|
}],
|
|
style: this.cssVars,
|
|
onClick: this.onClick,
|
|
onMouseenter: this.handleMouseEnter,
|
|
onMouseleave: this.handleMouseLeave,
|
|
onKeydown: this.onKeydown,
|
|
onFocusin: this.handleFocusin,
|
|
onFocusout: this.handleFocusout,
|
|
onMousedown: this.handleMouseDown
|
|
}, body, bordered ? h("div", {
|
|
class: `${clsPrefix}-base-selection__border`
|
|
}) : null, bordered ? h("div", {
|
|
class: `${clsPrefix}-base-selection__state-border`
|
|
}) : null);
|
|
}
|
|
}); |