@fesjs/fes-design
Version:
fes-design for PC
410 lines (403 loc) • 13.6 kB
JavaScript
import _defineProperty from '@babel/runtime/helpers/esm/defineProperty';
import { defineComponent, computed, ref, watch, resolveComponent, openBlock, createBlock, withCtx, normalizeClass, normalizeStyle, renderSlot, createVNode } from 'vue';
import { isValid, format } from 'date-fns';
import { isNil, isEqual, isArray } from 'lodash-es';
import InputInner from '../input/inputInner.js';
import Popper from '../popper';
import useFormAdaptor from '../_util/use/useFormAdaptor';
import { useNormalModel } from '../_util/use/useModel';
import getPrefixCls from '../_util/getPrefixCls';
import { useTheme } from '../_theme/useTheme';
import { DateOutlined, SwapRightOutlined } from '../icon';
import { useLocale } from '../config-provider/useLocale';
import { COMMON_PROPS, RANGE_PROPS } from './const';
import { strictParse, isEmptyValue } from './helper';
import Calendars from './calendars.js';
import RangeInput from './rangeInput.js';
import { pickerFactory, PickerType } from './pickerHandler';
import { useDisable } from './use';
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
const prefixCls = getPrefixCls('date-picker');
const datePickerProps = _objectSpread(_objectSpread({
open: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: false
},
placeholder: {
type: [String, Array]
},
appendToContainer: {
type: Boolean,
default: true
},
getContainer: {
type: Function
},
popperClass: [String, Array, Object],
control: Boolean,
shortcuts: Object,
disabledDate: Function
}, COMMON_PROPS), RANGE_PROPS);
const useTmpSelectedDates = () => {
const tmpSelectedDates = ref();
const tmpSelectedDateChange = val => {
tmpSelectedDates.value = val;
};
return {
tmpSelectedDates,
tmpSelectedDateChange
};
};
const useInput = _ref => {
let {
props,
visibleValue,
picker,
changeDateByInput
} = _ref;
const dateText = ref();
const {
innerDisabledDate
} = useDisable(props);
let cacheValidInputDate = '';
const getFormatDate = () => {
if (isEmptyValue(visibleValue.value)) {
return '';
}
if (!picker.value.isRange) {
if (isArray(visibleValue.value)) {
return visibleValue.value.map(item => {
return format(item, props.format || picker.value.format);
}).join('; ');
}
return format(visibleValue.value, props.format || picker.value.format);
}
return '';
};
const resetDateText = () => {
dateText.value = getFormatDate();
cacheValidInputDate = dateText.value;
};
watch([visibleValue, () => props.format], resetDateText, {
immediate: true
});
const handleDateInput = val => {
dateText.value = val;
const date = strictParse(val, props.format || picker.value.format, new Date());
if (isValid(date) && !innerDisabledDate(date, props.format || picker.value.format)) {
cacheValidInputDate = val;
changeDateByInput(date.getTime());
}
};
const handleDateInputBlur = () => {
if (dateText.value !== cacheValidInputDate && cacheValidInputDate) {
dateText.value = cacheValidInputDate;
}
};
return {
resetDateText,
dateText,
handleDateInput,
handleDateInputBlur
};
};
const usePlaceholder = (props, picker) => {
const {
t
} = useLocale();
const innerPlaceHolder = computed(() => {
if (props.placeholder) {
return props.placeholder;
}
const placeholderLang = picker.value.placeholderLang;
if (Array.isArray(placeholderLang)) {
return placeholderLang.map(item => t(item));
}
return t(placeholderLang);
});
const singlePlaceHolder = computed(() => {
return Array.isArray(innerPlaceHolder.value) ? innerPlaceHolder.value[0] : innerPlaceHolder.value;
});
return {
innerPlaceHolder,
singlePlaceHolder
};
};
var script = defineComponent({
name: 'FDatePicker',
components: {
Calendars,
InputInner,
Popper,
DateOutlined,
RangeInput,
SwapRightOutlined
},
props: datePickerProps,
emits: ['update:modelValue', 'update:open', 'change', 'clear', 'blur', 'focus'],
setup(props, _ref2) {
let {
emit,
attrs
} = _ref2;
useTheme();
const [isOpened, updatePopperOpen] = useNormalModel(props, emit, {
prop: 'open'
});
const [currentValue, updateCurrentValue] = useNormalModel(props, emit);
/**
* props.format 是最终给用户展示的格式,不必和 picker.value.format 一致
* picker.value.format 用于内部处理
*/
const pickerRef = computed(() => {
return pickerFactory(props.type);
});
const inputRefEl = ref();
const inputRangeRefEL = ref();
const calendarsRef = ref();
const activeInputRefEL = computed(() => {
if (pickerRef.value.isRange) {
return inputRangeRefEL.value;
}
return inputRefEl.value;
});
const {
validate,
isError,
isFormDisabled
} = useFormAdaptor({
valueType: computed(() => pickerRef.value.isRange ? 'array' : 'number'),
forbidChildValidate: true
});
const innerDisabled = computed(() => props.disabled || isFormDisabled.value);
const {
innerPlaceHolder,
singlePlaceHolder
} = usePlaceholder(props, pickerRef);
const {
tmpSelectedDates,
tmpSelectedDateChange
} = useTmpSelectedDates();
const visibleValue = computed(() => {
if (isOpened.value) {
return isNil(tmpSelectedDates.value) ? currentValue.value : tmpSelectedDates.value;
}
return currentValue.value;
});
const handleChange = val => {
if (!isEqual(val, currentValue.value)) {
updateCurrentValue(val);
emit('change', val);
validate('change');
}
};
// 输入框里的变更,直接更新 currentValue
const changeDateByInput = val => {
tmpSelectedDateChange(null);
handleChange(val);
};
const {
resetDateText,
dateText,
handleDateInput,
handleDateInputBlur
} = useInput({
props,
visibleValue,
changeDateByInput,
picker: pickerRef
});
// 事件
const clear = () => {
const initValue = pickerRef.value.isRange || pickerRef.value.name === PickerType.datemultiple ? [] : null;
tmpSelectedDateChange(null);
handleChange(initValue);
emit('clear');
};
const changeDateBycalendars = val => {
handleChange(val);
// 选择完后重新聚焦
activeInputRefEL.value.focus();
updatePopperOpen(false);
};
const inputIsFocus = ref(false);
const handleFocus = e => {
// 防止重复聚焦
if (!inputIsFocus.value) {
inputIsFocus.value = true;
emit('focus', e);
}
};
let cacheEvent = null;
const checkBlur = () => {
if (!isOpened.value && cacheEvent) {
emit('blur', cacheEvent);
validate('blur');
// 重置输入框内容
resetDateText();
cacheEvent = null;
inputIsFocus.value = false;
}
};
const handleBlur = e => {
var _calendarsRef$value;
cacheEvent = e;
// 非弹窗内容点击导致的失焦,进行 blur 的校验
// 兼容禁用状态,选择框不展示的情况
if (!((_calendarsRef$value = calendarsRef.value) !== null && _calendarsRef$value !== void 0 && _calendarsRef$value.$el.contains(e.relatedTarget))) {
if (isOpened.value) {
updatePopperOpen(false);
}
checkBlur();
}
};
watch(isOpened, () => {
if (!isOpened.value) {
// 重置临时输入
tmpSelectedDateChange(null);
}
});
const handlePopperVisible = val => {
if (val === false) {
checkBlur();
}
};
return {
prefixCls,
isOpened,
currentValue,
visibleValue,
isError,
innerDisabled,
dateText,
handleDateInput,
handleDateInputBlur: event => {
handleDateInputBlur();
handleBlur(event);
},
PickerType,
pickerRef,
changeDateByInput,
clear,
changeDateBycalendars,
inputIsFocus,
handleFocus,
handleBlur,
tmpSelectedDateChange,
innerPlaceHolder,
singlePlaceHolder,
handlePopperVisible,
inputRefEl,
inputRangeRefEL,
calendarsRef,
attrs
};
}
});
function render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_SwapRightOutlined = resolveComponent("SwapRightOutlined");
const _component_DateOutlined = resolveComponent("DateOutlined");
const _component_RangeInput = resolveComponent("RangeInput");
const _component_InputInner = resolveComponent("InputInner");
const _component_calendars = resolveComponent("calendars");
const _component_Popper = resolveComponent("Popper");
return openBlock(), createBlock(_component_Popper, {
modelValue: _ctx.isOpened,
"onUpdate:modelValue": [_cache[0] || (_cache[0] = $event => _ctx.isOpened = $event), _ctx.handlePopperVisible],
disabled: _ctx.innerDisabled,
appendToContainer: _ctx.appendToContainer,
getContainer: _ctx.getContainer,
popperClass: [_ctx.popperClass, `${_ctx.prefixCls}-popper`],
trigger: "click",
hideAfter: 0,
placement: "bottom-start",
offset: 4,
onlyShowTrigger: ""
}, {
trigger: withCtx(() => [_ctx.pickerRef.isRange ? (openBlock(), createBlock(_component_RangeInput, {
key: 0,
ref: "inputRangeRefEL",
format: _ctx.format || _ctx.pickerRef.format,
selectedDates: _ctx.visibleValue,
placeholder: _ctx.innerPlaceHolder,
clearable: _ctx.clearable,
disabled: _ctx.innerDisabled,
innerIsFocus: _ctx.inputIsFocus,
innerIsError: _ctx.isError,
class: normalizeClass(_ctx.attrs.class),
style: normalizeStyle(_ctx.attrs.style),
changeSelectedDates: _ctx.changeDateByInput,
maxRange: _ctx.maxRange,
onFocus: _ctx.handleFocus,
onBlur: _ctx.handleBlur,
onClear: _ctx.clear
}, {
separator: withCtx(() => [_ctx.$slots.separator ? renderSlot(_ctx.$slots, "separator", {
key: 0
}) : (openBlock(), createBlock(_component_SwapRightOutlined, {
key: 1
}))]),
suffix: withCtx(() => [_ctx.$slots.suffixIcon ? renderSlot(_ctx.$slots, "suffixIcon", {
key: 0
}) : (openBlock(), createBlock(_component_DateOutlined, {
key: 1
}))]),
_: 3 /* FORWARDED */
}, 8 /* PROPS */, ["format", "selectedDates", "placeholder", "clearable", "disabled", "innerIsFocus", "innerIsError", "class", "style", "changeSelectedDates", "maxRange", "onFocus", "onBlur", "onClear"])) : (openBlock(), createBlock(_component_InputInner, {
key: 1,
ref: "inputRefEl",
modelValue: _ctx.dateText,
placeholder: _ctx.singlePlaceHolder,
disabled: _ctx.innerDisabled,
canEdit: _ctx.pickerRef.name !== _ctx.PickerType.datemultiple,
clearable: _ctx.clearable,
innerIsFocus: _ctx.inputIsFocus,
innerIsError: _ctx.isError,
class: normalizeClass(_ctx.attrs.class),
style: normalizeStyle(_ctx.attrs.style),
onFocus: _ctx.handleFocus,
onInput: _ctx.handleDateInput,
onBlur: _ctx.handleDateInputBlur,
onClear: _ctx.clear
}, {
suffix: withCtx(() => [_ctx.$slots.suffixIcon ? renderSlot(_ctx.$slots, "suffixIcon", {
key: 0
}) : (openBlock(), createBlock(_component_DateOutlined, {
key: 1
}))]),
_: 3 /* FORWARDED */
}, 8 /* PROPS */, ["modelValue", "placeholder", "disabled", "canEdit", "clearable", "innerIsFocus", "innerIsError", "class", "style", "onFocus", "onInput", "onBlur", "onClear"]))]),
default: withCtx(() => [createVNode(_component_calendars, {
ref: "calendarsRef",
visible: _ctx.isOpened,
modelValue: _ctx.currentValue,
type: _ctx.type,
control: _ctx.control,
shortcuts: _ctx.shortcuts,
minDate: _ctx.minDate,
maxDate: _ctx.maxDate,
maxRange: _ctx.maxRange,
hourStep: _ctx.hourStep,
minuteStep: _ctx.minuteStep,
secondStep: _ctx.secondStep,
disabledDate: _ctx.disabledDate,
disabledTime: _ctx.disabledTime,
defaultTime: _ctx.defaultTime,
onChange: _ctx.changeDateBycalendars,
onTmpSelectedDateChange: _ctx.tmpSelectedDateChange
}, null, 8 /* PROPS */, ["visible", "modelValue", "type", "control", "shortcuts", "minDate", "maxDate", "maxRange", "hourStep", "minuteStep", "secondStep", "disabledDate", "disabledTime", "defaultTime", "onChange", "onTmpSelectedDateChange"])]),
_: 3 /* FORWARDED */
}, 8 /* PROPS */, ["modelValue", "disabled", "appendToContainer", "getContainer", "popperClass", "onUpdate:modelValue"]);
}
script.render = render;
script.__file = "components/date-picker/datePicker.vue";
export { datePickerProps, script as default };