import { ref, watch, computed, nextTick, defineComponent, createVNode as _createVNode, mergeProps as _mergeProps } from "vue"; import { pick, extend, unitToPx, truthProp, isSameValue, makeArrayProp, preventDefault, makeStringProp, makeNumericProp, BORDER_UNSET_TOP_BOTTOM } from "../utils/index.mjs"; import { bem, name, isOptionExist, getColumnsType, findOptionByValue, assignDefaultFields, formatCascadeColumns, getFirstEnabledOption } from "./utils.mjs"; import { useChildren, useEventListener, useParent } from "@vant/use"; import { useExpose } from "../composables/use-expose.mjs"; import { Loading } from "../loading/index.mjs"; import Column, { PICKER_KEY } from "./PickerColumn.mjs"; import Toolbar, { pickerToolbarPropKeys, pickerToolbarProps, pickerToolbarSlots } from "./PickerToolbar.mjs"; import { PICKER_GROUP_KEY } from "../picker-group/PickerGroup.mjs"; const pickerSharedProps = extend({ loading: Boolean, readonly: Boolean, allowHtml: Boolean, optionHeight: makeNumericProp(44), showToolbar: truthProp, swipeDuration: makeNumericProp(1e3), visibleOptionNum: makeNumericProp(6) }, pickerToolbarProps); const pickerProps = extend({}, pickerSharedProps, { columns: makeArrayProp(), modelValue: makeArrayProp(), toolbarPosition: makeStringProp("top"), columnsFieldNames: Object }); var stdin_default = defineComponent({ name, props: pickerProps, emits: ["confirm", "cancel", "change", "scrollInto", "clickOption", "update:modelValue"], setup(props, { emit, slots }) { const columnsRef = ref(); const selectedValues = ref(props.modelValue.slice(0)); const { parent } = useParent(PICKER_GROUP_KEY); const { children, linkChildren } = useChildren(PICKER_KEY); linkChildren(); const fields = computed(() => assignDefaultFields(props.columnsFieldNames)); const optionHeight = computed(() => unitToPx(props.optionHeight)); const columnsType = computed(() => getColumnsType(props.columns, fields.value)); const currentColumns = computed(() => { const { columns } = props; switch (columnsType.value) { case "multiple": return columns; case "cascade": return formatCascadeColumns(columns, fields.value, selectedValues); default: return [columns]; } }); const hasOptions = computed(() => currentColumns.value.some((options) => options.length)); const selectedOptions = computed(() => currentColumns.value.map((options, index) => findOptionByValue(options, selectedValues.value[index], fields.value))); const selectedIndexes = computed(() => currentColumns.value.map((options, index) => options.findIndex((option) => option[fields.value.value] === selectedValues.value[index]))); const setValue = (index, value) => { if (selectedValues.value[index] !== value) { const newValues = selectedValues.value.slice(0); newValues[index] = value; selectedValues.value = newValues; } }; const getEventParams = () => ({ selectedValues: selectedValues.value.slice(0), selectedOptions: selectedOptions.value, selectedIndexes: selectedIndexes.value }); const onChange = (value, columnIndex) => { setValue(columnIndex, value); if (columnsType.value === "cascade") { selectedValues.value.forEach((value2, index) => { const options = currentColumns.value[index]; if (!isOptionExist(options, value2, fields.value)) { setValue(index, options.length ? options[0][fields.value.value] : void 0); } }); } nextTick(() => { emit("change", extend({ columnIndex }, getEventParams())); }); }; const onClickOption = (currentOption, columnIndex) => { const params = { columnIndex, currentOption }; emit("clickOption", extend(getEventParams(), params)); emit("scrollInto", params); }; const confirm = () => { children.forEach((child) => child.stopMomentum()); const params = getEventParams(); nextTick(() => { emit("confirm", params); }); return params; }; const cancel = () => emit("cancel", getEventParams()); const renderColumnItems = () => currentColumns.value.map((options, columnIndex) => _createVNode(Column, { "value": selectedValues.value[columnIndex], "fields": fields.value, "options": options, "readonly": props.readonly, "allowHtml": props.allowHtml, "optionHeight": optionHeight.value, "swipeDuration": props.swipeDuration, "visibleOptionNum": props.visibleOptionNum, "onChange": (value) => onChange(value, columnIndex), "onClickOption": (option) => onClickOption(option, columnIndex), "onScrollInto": (option) => { emit("scrollInto", { currentOption: option, columnIndex }); } }, { option: slots.option })); const renderMask = (wrapHeight) => { if (hasOptions.value) { const frameStyle = { height: `${optionHeight.value}px` }; const maskStyle = { backgroundSize: `100% ${(wrapHeight - optionHeight.value) / 2}px` }; return [_createVNode("div", { "class": bem("mask"), "style": maskStyle }, null), _createVNode("div", { "class": [BORDER_UNSET_TOP_BOTTOM, bem("frame")], "style": frameStyle }, null)]; } }; const renderColumns = () => { const wrapHeight = optionHeight.value * +props.visibleOptionNum; const columnsStyle = { height: `${wrapHeight}px` }; if (!props.loading && !hasOptions.value && slots.empty) { return slots.empty(); } return _createVNode("div", { "ref": columnsRef, "class": bem("columns"), "style": columnsStyle }, [renderColumnItems(), renderMask(wrapHeight)]); }; const renderToolbar = () => { if (props.showToolbar && !parent) { return _createVNode(Toolbar, _mergeProps(pick(props, pickerToolbarPropKeys), { "onConfirm": confirm, "onCancel": cancel }), pick(slots, pickerToolbarSlots)); } }; watch(currentColumns, (columns) => { columns.forEach((options, index) => { if (options.length && !isOptionExist(options, selectedValues.value[index], fields.value)) { setValue(index, getFirstEnabledOption(options)[fields.value.value]); } }); }, { immediate: true }); let lastEmittedModelValue; watch(() => props.modelValue, (newValues) => { if (!isSameValue(newValues, selectedValues.value) && !isSameValue(newValues, lastEmittedModelValue)) { selectedValues.value = newValues.slice(0); lastEmittedModelValue = newValues.slice(0); } }, { deep: true }); watch(selectedValues, (newValues) => { if (!isSameValue(newValues, props.modelValue)) { lastEmittedModelValue = newValues.slice(0); emit("update:modelValue", lastEmittedModelValue); } }, { immediate: true }); useEventListener("touchmove", preventDefault, { target: columnsRef }); const getSelectedOptions = () => selectedOptions.value; useExpose({ confirm, getSelectedOptions }); return () => { var _a, _b; return _createVNode("div", { "class": bem() }, [props.toolbarPosition === "top" ? renderToolbar() : null, props.loading ? _createVNode(Loading, { "class": bem("loading") }, null) : null, (_a = slots["columns-top"]) == null ? void 0 : _a.call(slots), renderColumns(), (_b = slots["columns-bottom"]) == null ? void 0 : _b.call(slots), props.toolbarPosition === "bottom" ? renderToolbar() : null]); }; } }); export { stdin_default as default, pickerProps, pickerSharedProps };