naive-ui
Version:
A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast
267 lines • 8.28 kB
JavaScript
import { happensIn } from 'seemly';
import { useMemo } from 'vooks';
import { computed, defineComponent, h, inject, Transition } from 'vue';
import { NBaseIcon, NBaseLoading } from "../../_internal/index.mjs";
import { CheckmarkIcon, ChevronRightIcon } from "../../_internal/icons/index.mjs";
import { NCheckbox } from "../../checkbox/index.mjs";
import { cascaderInjectionKey } from "./interface.mjs";
export default defineComponent({
name: 'NCascaderOption',
props: {
tmNode: {
type: Object,
required: true
}
},
setup(props) {
const {
expandTriggerRef,
remoteRef,
multipleRef,
mergedValueRef,
checkedKeysRef,
indeterminateKeysRef,
hoverKeyPathRef,
keyboardKeyRef,
loadingKeySetRef,
cascadeRef,
mergedCheckStrategyRef,
onLoadRef,
mergedClsPrefixRef,
mergedThemeRef,
labelFieldRef,
showCheckboxRef,
renderPrefixRef,
renderSuffixRef,
updateHoverKey,
updateKeyboardKey,
addLoadingKey,
deleteLoadingKey,
closeMenu,
doCheck,
doUncheck,
renderLabelRef
} = inject(cascaderInjectionKey);
const valueRef = computed(() => props.tmNode.key);
const useHoverTriggerRef = computed(() => {
const {
value: expandTrigger
} = expandTriggerRef;
const {
value: remote
} = remoteRef;
return !remote && expandTrigger === 'hover';
});
const mergedHandleMouseEnterRef = computed(() => {
if (useHoverTriggerRef.value) {
return handleMouseEnter;
}
return undefined;
});
const mergedHandleMouseMoveRef = computed(() => {
if (useHoverTriggerRef.value) {
return handleMouseMove;
}
return undefined;
});
const checkedRef = useMemo(() => {
const {
value: multiple
} = multipleRef;
if (!multiple) return mergedValueRef.value === valueRef.value;
return checkedKeysRef.value.includes(valueRef.value);
});
const indeterminateRef = useMemo(() => {
if (!multipleRef.value) return false;
return indeterminateKeysRef.value.includes(valueRef.value);
});
const hoverPendingRef = useMemo(() => {
return hoverKeyPathRef.value.includes(valueRef.value);
});
const keyboardPendingRef = useMemo(() => {
const {
value: keyboardKey
} = keyboardKeyRef;
if (keyboardKey === null) return false;
return keyboardKey === valueRef.value;
});
const isLoadingRef = useMemo(() => {
if (remoteRef.value) {
return loadingKeySetRef.value.has(valueRef.value);
}
return false;
});
const isLeafRef = computed(() => props.tmNode.isLeaf);
const disabledRef = computed(() => props.tmNode.disabled);
const labelRef = computed(() => props.tmNode.rawNode[labelFieldRef.value]);
const isShallowLoadedRef = computed(() => {
return props.tmNode.shallowLoaded;
});
function handleClick(e) {
if (disabledRef.value) return;
const {
value: remote
} = remoteRef;
const {
value: loadingKeySet
} = loadingKeySetRef;
const {
value: onLoad
} = onLoadRef;
const {
value
} = valueRef;
const {
value: isLeaf
} = isLeafRef;
const {
value: isShallowLoaded
} = isShallowLoadedRef;
if (!happensIn(e, 'checkbox')) {
if (remote && !isShallowLoaded && !loadingKeySet.has(value) && onLoad) {
addLoadingKey(value);
onLoad(props.tmNode.rawNode).then(() => {
deleteLoadingKey(value);
}).catch(() => {
deleteLoadingKey(value);
});
}
updateHoverKey(value);
updateKeyboardKey(value);
}
if (isLeaf) {
toggleCheckbox();
}
}
function handleMouseEnter() {
if (!useHoverTriggerRef.value || disabledRef.value) return;
const {
value
} = valueRef;
updateHoverKey(value);
updateKeyboardKey(value);
}
function handleMouseMove() {
if (!useHoverTriggerRef.value) return;
handleMouseEnter();
}
function handleCheckboxUpdateValue() {
const {
value: isLeaf
} = isLeafRef;
if (!isLeaf) toggleCheckbox();
}
function toggleCheckbox() {
const {
value: multiple
} = multipleRef;
const {
value
} = valueRef;
if (multiple) {
if (indeterminateRef.value || checkedRef.value) {
doUncheck(value);
} else {
doCheck(value);
}
} else {
doCheck(value);
closeMenu(true);
}
}
return {
checkStrategy: mergedCheckStrategyRef,
multiple: multipleRef,
cascade: cascadeRef,
checked: checkedRef,
indeterminate: indeterminateRef,
hoverPending: hoverPendingRef,
keyboardPending: keyboardPendingRef,
isLoading: isLoadingRef,
showCheckbox: showCheckboxRef,
isLeaf: isLeafRef,
disabled: disabledRef,
label: labelRef,
mergedClsPrefix: mergedClsPrefixRef,
mergedTheme: mergedThemeRef,
handleClick,
handleCheckboxUpdateValue,
mergedHandleMouseEnter: mergedHandleMouseEnterRef,
mergedHandleMouseMove: mergedHandleMouseMoveRef,
renderLabel: renderLabelRef,
renderPrefix: renderPrefixRef,
renderSuffix: renderSuffixRef
};
},
render() {
const {
mergedClsPrefix,
showCheckbox,
renderLabel,
renderPrefix,
renderSuffix
} = this;
let prefixNode = null;
if (showCheckbox || renderPrefix) {
const originalNode = this.showCheckbox ? h(NCheckbox, {
focusable: false,
"data-checkbox": true,
disabled: this.disabled,
checked: this.checked,
indeterminate: this.indeterminate,
theme: this.mergedTheme.peers.Checkbox,
themeOverrides: this.mergedTheme.peerOverrides.Checkbox,
onUpdateChecked: this.handleCheckboxUpdateValue
}) : null;
prefixNode = h("div", {
class: `${mergedClsPrefix}-cascader-option__prefix`
}, renderPrefix ? renderPrefix({
option: this.tmNode.rawNode,
checked: this.checked,
node: originalNode
}) : originalNode);
}
let suffixNode = null;
const originalSuffixChild = h("div", {
class: `${mergedClsPrefix}-cascader-option-icon-placeholder`
}, !this.isLeaf ? h(NBaseLoading, {
clsPrefix: mergedClsPrefix,
scale: 0.85,
strokeWidth: 24,
show: this.isLoading,
class: `${mergedClsPrefix}-cascader-option-icon`
}, {
default: () => h(NBaseIcon, {
clsPrefix: mergedClsPrefix,
key: "arrow",
class: `${mergedClsPrefix}-cascader-option-icon ${mergedClsPrefix}-cascader-option-icon--arrow`
}, {
default: () => h(ChevronRightIcon, null)
})
}) : this.checkStrategy === 'child' && !(this.multiple && this.cascade) ? h(Transition, {
name: "fade-in-scale-up-transition"
}, {
default: () => this.checked ? h(NBaseIcon, {
clsPrefix: mergedClsPrefix,
class: `${mergedClsPrefix}-cascader-option-icon ${mergedClsPrefix}-cascader-option-icon--checkmark`
}, {
default: () => h(CheckmarkIcon, null)
}) : null
}) : null);
suffixNode = h("div", {
class: `${mergedClsPrefix}-cascader-option__suffix`
}, renderSuffix ? renderSuffix({
option: this.tmNode.rawNode,
checked: this.checked,
node: originalSuffixChild
}) : originalSuffixChild);
return h("div", {
class: [`${mergedClsPrefix}-cascader-option`, this.keyboardPending || this.hoverPending && `${mergedClsPrefix}-cascader-option--pending`, this.disabled && `${mergedClsPrefix}-cascader-option--disabled`, this.showCheckbox && `${mergedClsPrefix}-cascader-option--show-prefix`],
onMouseenter: this.mergedHandleMouseEnter,
onMousemove: this.mergedHandleMouseMove,
onClick: this.handleClick
}, prefixNode, h("span", {
class: `${mergedClsPrefix}-cascader-option__label`
}, renderLabel ? renderLabel(this.tmNode.rawNode, this.checked) : this.label), suffixNode);
}
});