UNPKG

@opentiny/vue-renderless

Version:

An enterprise-class UI component library, support both Vue.js 2 and Vue.js 3, as well as PC and mobile.

1,125 lines (1,124 loc) 38.6 kB
import { __spreadProps, __spreadValues } from "../chunk-G2ADBYYC.js"; import { toDate1, getDateWithNewTimezone, getStrTimezone, getLocalTimezone } from "@opentiny/utils"; import { isNumber, isDate } from "@opentiny/utils"; import { userPopper } from "@opentiny/vue-hooks"; import { DATEPICKER } from "@opentiny/utils"; import { formatDate, parseDate1 as parseDate, isDateObject, getWeekNumber, prevDate, nextDate } from "@opentiny/utils"; import { extend } from "@opentiny/utils"; import globalTimezone from "./timezone"; const iso8601Reg = /^\d{4}-\d{2}-\d{2}(.)\d{2}:\d{2}:\d{2}(.+)$/; const getPanel = ({ DatePanel, DateRangePanel, MonthRangePanel, YearRangePanel, TimePanel, TimeRangePanel, QuarterPanel, TimeSelect }) => (type) => { if (type === DATEPICKER.DateRange || type === DATEPICKER.DateTimeRange) { return DateRangePanel; } else if (type === DATEPICKER.MonthRange) { return MonthRangePanel; } else if (type === DATEPICKER.YearRange) { return YearRangePanel; } else if (type === DATEPICKER.TimeRange) { return TimeRangePanel; } else if (type === DATEPICKER.Time) { return TimePanel; } else if (type === DATEPICKER.TimeSelect) { return TimeSelect; } else if (type === DATEPICKER.Quarter) { return QuarterPanel; } return DatePanel; }; const watchMobileVisible = ({ api, props, state, nextTick }) => ([dateMobileVisible, timeMobileVisible]) => { if (dateMobileVisible || timeMobileVisible) { state.valueOnOpen = Array.isArray(props.modelValue) ? [...props.modelValue] : props.modelValue; } else { nextTick(() => { api.emitChange(props.modelValue); }); } }; const watchPickerVisible = ({ api, vm, dispatch, emit, props, state, nextTick, isPCMode }) => (value) => { if (props.readonly || state.pickerDisabled || state.isMobileScreen && !isPCMode) return; if (value) { api.showPicker(); state.valueOnOpen = Array.isArray(props.modelValue) ? [...props.modelValue] : props.modelValue; } else { api.hidePicker(); nextTick(() => { api.emitChange(props.modelValue); }); state.userInput = null; if (props.validateEvent) { dispatch("FormItem", "form.blur"); } if (props.changeOnConfirm && !valueEquals(props.modelValue, state.oldValue)) { emit("update:modelValue", state.oldValue); } emit("blur", vm); api.blur(); } }; const getValueEmpty = (props) => () => { const modelValue = props.modelValue; if (Array.isArray(modelValue)) { for (let i = 0, len = modelValue.length; i < len; i++) { if (modelValue[i]) { return false; } } } else { if (modelValue) { return false; } } return true; }; const getMode = ({ state }) => () => { if (state.type === DATEPICKER.Week) { return DATEPICKER.Week; } else if (state.type === DATEPICKER.Month) { return DATEPICKER.Month; } else if ([DATEPICKER.Year, DATEPICKER.Years, DATEPICKER.YearRange].includes(state.type)) { return state.type; } else if (state.type === DATEPICKER.Dates) { return DATEPICKER.Dates; } return DATEPICKER.Day; }; const formatAsFormatAndType = ({ api }) => (value, customFormat, type, formatObj) => { if (!value) return null; const formatter = (api.typeValueResolveMap()[type] || api.typeValueResolveMap().default).formatter; const format = customFormat || DATEPICKER.DateFormats[type]; return formatter(value, format, formatObj); }; const displayValue = ({ api, props, state }) => () => { const formatObj = { rangeSeparator: props.rangeSeparator }; const formattedValue = api.formatAsFormatAndType(state.parsedValue, state.format, state.type, formatObj); if (Array.isArray(state.userInput)) { return [ state.userInput[0] || formattedValue && formattedValue[0] || "", state.userInput[1] || formattedValue && formattedValue[1] || "" ]; } else if (state.userInput !== null) { return state.userInput; } else if (formattedValue) { return [DATEPICKER.Dates, DATEPICKER.Years].includes(state.type) ? formattedValue.join(", ") : formattedValue; } return ""; }; const parseAsFormatAndType = ({ api }) => (value, customFormat, type, rangeSeparator = "-") => { if (!value) { return null; } const parser = (api.typeValueResolveMap()[type] || api.typeValueResolveMap().default).parser; const format = customFormat || DATEPICKER.DateFormats[type]; return parser(value, format, rangeSeparator); }; const parsedValue = ({ api, props, state, t }) => () => { if (!props.modelValue) { return props.modelValue; } if (state.type === DATEPICKER.TimeSelect) { return props.modelValue; } const valueIsDateObject = isDateObject(props.modelValue) || Array.isArray(props.modelValue) && props.modelValue.every(isDateObject); const { from, to, isServiceTimezone, timezoneOffset } = state.timezone; if (valueIsDateObject && !isServiceTimezone) { return props.modelValue; } if (state.valueFormat) { let date = props.modelValue; if (isServiceTimezone) { if (Array.isArray(date)) { date = [].concat(date).map((item) => { return isDate(item) ? formatDate(item, state.valueFormat, t) : item; }); } else { if (state.valueFormat !== DATEPICKER.TimesTamp) { date = formatDate(date, state.valueFormat, t); } } } const result = api.parseAsFormatAndType(date, state.valueFormat, state.type, props.rangeSeparator); if (Array.isArray(result)) { return result.map((date2) => getDateWithNewTimezone(date2, from, to, timezoneOffset)); } return getDateWithNewTimezone(result || props.modelValue, from, to, timezoneOffset); } const trans = (value) => typeof value === "string" || isNumber(value) ? toDate1(value) : value; const values = [].concat(props.modelValue).map((val) => getDateWithNewTimezone(trans(val), from, to, timezoneOffset)); return values.length > 1 ? values : values[0]; }; const getTimezone = ({ props, utils }) => () => { const { dbTimezone, timezone, isutc8, type = "date", iso8601, timezoneOffset } = props; const setting = utils.getDateFormat && utils.getDateFormat(); const { DbTimezone, Timezone, TimezoneOffset } = setting || {}; const cur = getLocalTimezone(); const isTzNumber = (z) => typeof z === "number" && z >= -12 && z <= 14; if (!~type.indexOf("datetime")) { return { from: cur, to: cur }; } let serveTimezone = isTzNumber(dbTimezone) ? dbTimezone : isTzNumber(DbTimezone) ? DbTimezone : cur; let clientTimezone = isTzNumber(timezone) ? timezone : isTzNumber(Timezone) ? Timezone : cur; let clientTimezoneOffset = isNumber(timezoneOffset) ? timezoneOffset : isNumber(TimezoneOffset) ? TimezoneOffset : 0; const value = props.modelValue; const str = (Array.isArray(value) ? value[0] : value) || ""; const match = typeof str === "string" && str.match(/(-|\+)(\d{2}):?(\d{2})$/); if ((iso8601 || setting) && match) { serveTimezone = getStrTimezone(str); } return { from: serveTimezone, to: isutc8 ? 8 : clientTimezone, isServiceTimezone: !!setting, timezoneOffset: clientTimezoneOffset }; }; const nullOrString = (value) => { const arr = Array.isArray(value) ? value : [value]; return arr.every((val) => !val && !isNumber(val) || typeof val === "string"); }; const getValueFormat = ({ props, utils }) => { const { valueFormat, iso8601, modelValue: value, type = "date" } = props; const setting = utils.getDateFormat && utils.getDateFormat(); let suffix = ""; let separator = " "; if (!valueFormat && ~type.indexOf("datetime") && (iso8601 || setting) && nullOrString(value)) { const str = (Array.isArray(value) ? value[0] : value) || ""; const match = str.match(iso8601Reg); if (match && match.length === 3) { suffix = match[2] || ""; separator = match[1]; } return `yyyy-MM-dd${separator}HH:mm:ss${suffix}`; } return valueFormat; }; const dateFormatter = ({ t }) => (value, format) => { if (format === DATEPICKER.TimesTamp) { return value.getTime(); } return formatDate(value, format, t); }; const dateParser = ({ t, props }) => (text, format) => { if (format === DATEPICKER.TimesTamp) { return new Date(Number(text)); } const value = props.autoFormat ? formatText({ text, format }) : text; return parseDate(value, format, t); }; const rangeFormatter = (api) => (value, format) => { if (Array.isArray(value) && value.length === 2) { const start = value[0]; const end = value[1]; if (start && end) { return [api.dateFormatter(start, format), api.dateFormatter(end, format)]; } } return ""; }; const rangeParser = (api) => (array, format, separator) => { if (!Array.isArray(array)) { array = array.split(separator); } if (array.length === 2) { const range1 = array[0]; const range2 = array[1]; return [api.dateParser(range1, format), api.dateParser(range2, format)]; } return []; }; const getWeekData = (value) => { const valueday = new Date(value).getDay(); let newDate = new Date(value); if (valueday >= 2) { newDate.setTime(new Date(value).getTime() - (valueday - 1) * 864e5); } else if (valueday === 0) { newDate.setTime(new Date(value).getTime() + (valueday + 1) * 864e5); } return newDate; }; const getDefaultOfTypeValueResolveMap = () => ({ formatter(value) { return value ? String(value) : ""; }, parser(text) { return text === void 0 || text === "" ? null : text; } }); const getWeekOfTypeValueResolveMap = ({ t, props, api }) => ({ formatter(value, format, formatObj) { const weekDate = getWeekData(value); let week = getWeekNumber(weekDate); let month = weekDate.getMonth(); const trueDate = new Date(weekDate); const { rangeSeparator = "-", type = "format" } = formatObj; if (week === 1 && month === 11) { trueDate.setHours(0, 0, 0, 0); trueDate.setDate(trueDate.getDate() + 3 - (trueDate.getDay() + 6) % 7); } let date; if (type === "format" && !/W/.test(format)) { const { start, end } = getWeekRange(value, format, t, props.pickerOptions); date = `${start} ${rangeSeparator} ${end}`; } else { date = formatDate(trueDate, format, t); date = /WW/.test(date) ? date.replace(/WW/, week < 10 ? "0" + week : week) : date.replace(/W/, week); } return date; }, parser(text, format) { return api.typeValueResolveMap().date.parser(text, format); } }); const getWeekRange = (value, format, t, pickerOptions) => { const firstDayOfWeek = pickerOptions && pickerOptions.firstDayOfWeek ? pickerOptions.firstDayOfWeek : 7; const dayOffset = (value.getDay() - firstDayOfWeek + 7) % 7; const startDate = prevDate(value, dayOffset); const endDate = nextDate(startDate, 6); const start = formatDate(startDate, format, t); const end = formatDate(endDate, format, t); return { start, end }; }; const getNumberOfTypeValueResolveMap = () => ({ formatter(value) { return value ? String(value) : ""; }, parser(text) { let result = Number(text); return !isNaN(text) ? result : null; } }); const getDatesOfTypeValueResolveMap = (api) => ({ formatter(value, format) { return value.map((date) => api.dateFormatter(date, format)); }, parser(value, format) { return (typeof value === "string" ? value.split(", ") : value).map( (date) => date instanceof Date ? date : api.dateParser(date, format) ); } }); const typeValueResolveMap = ({ api, props, t }) => () => ({ default: getDefaultOfTypeValueResolveMap(), week: getWeekOfTypeValueResolveMap({ t, props, api }), date: { formatter: api.dateFormatter, parser: api.dateParser }, datetime: { formatter: api.dateFormatter, parser: api.dateParser }, daterange: { formatter: api.rangeFormatter, parser: api.rangeParser }, monthrange: { formatter: api.rangeFormatter, parser: api.rangeParser }, datetimerange: { formatter: api.rangeFormatter, parser: api.rangeParser }, timerange: { formatter: api.rangeFormatter, parser: api.rangeParser }, time: { formatter: api.dateFormatter, parser: api.dateParser }, month: { formatter: api.dateFormatter, parser: api.dateParser }, year: { formatter: api.dateFormatter, parser: api.dateParser }, years: getDatesOfTypeValueResolveMap(api), yearrange: getDatesOfTypeValueResolveMap(api), number: getNumberOfTypeValueResolveMap(), dates: getDatesOfTypeValueResolveMap(api), quarter: { formatter: (value) => `${value.getFullYear()}-Q${DATEPICKER.MonthQuarterMap[value.getMonth()]}`, parser: api.dateParser } }); const firstInputId = ({ props, state }) => () => { const obj = {}; let id; if (state.ranged) { id = props.id && props.id[0]; } else { id = props.id; } if (id) { obj.id = id; } return obj; }; const secondInputId = ({ props, state }) => () => { const obj = {}; let id; if (state.ranged) { id = props.id && props.id[1]; } if (id) { obj.id = id; } return obj; }; const focus = ({ api, props, vm }) => () => !props.isRange ? vm.$refs.reference.querySelector("input").focus() : api.handleFocus(); const blur = (state) => () => state.refInput.forEach((input) => input.blur()); const parseValue = ({ api, props, state }) => (value) => { const isParsed = isDateObject(value) || Array.isArray(value) && value.every(isDateObject); if (state.valueFormat && !isParsed) { return api.parseAsFormatAndType(value, state.valueFormat, state.type, props.rangeSeparator) || value; } return value; }; const formatToValue = ({ api, state }) => (date) => { const isFormattable = isDateObject(date) || Array.isArray(date) && date.every(isDateObject); if (state.valueFormat && isFormattable) { return api.formatAsFormatAndType(date, state.valueFormat, state.type, { type: "value-format" }); } return date; }; const parseString = ({ api, state }) => (value) => { const type = Array.isArray(value) ? state.type : state.type.replace(DATEPICKER.Range, ""); return api.parseAsFormatAndType(value, state.format, type); }; const formatToString = ({ api, state }) => (value) => { const type = Array.isArray(value) ? state.type : state.type.replace(DATEPICKER.Range, ""); return api.formatAsFormatAndType(value, state.format, type); }; const handleMouseEnter = ({ props, state }) => () => { if (props.readonly || state.pickerDisabled) { return; } if (!state.valueIsEmpty && props.clearable) { state.showClose = true; } }; const handleInput = ({ state, props, api }) => (val, event) => { event = val.target ? val : event; if (props.autoFormat) { const value = api.formatInputValue({ event, prevValue: state.displayValue }); state.userInput = value; } else { const val2 = event.target.value; state.userInput = val2; } if (state.type === "time-select") { state.picker.state.isFilter = true; state.picker.state.filterVal = state.userInput; } }; const formatInputValue = ({ props, state }) => ({ event, prevValue = "" }) => { const val = event.target.value; const inputData = event.data; const format = state.type === "time-select" ? "HH:mm" : props.format || DATEPICKER.DateFormats[state.type]; if (inputData && inputData.charCodeAt() >= 48 && inputData.charCodeAt() <= 57) { return formatText({ event, format, text: prevValue, needSelectionStart: true }); } else { return val; } }; const getSelectionStart = ({ value, format, regx, event }) => { const formatMatchArr = format.match(regx); let selectionStart = getSelectionStartIndex(event); let I = 0; if (value !== "") { const match = value.match(/[0-9]/g); I = match === null ? 0 : match.length; for (let i = 0; i < formatMatchArr.length; i++) { I -= Math.max(formatMatchArr[i].length, 2); } I = I >= 0 ? 1 : 0; I === 1 && selectionStart >= value.length && (selectionStart = value.length - 1); } return { selectionStart, I }; }; const getEffectiveDateString = (formatStr) => { const serializationList = [{ "MM": "01" }, { "M": "1" }, { "dd": "01" }, { "d": "1" }]; let result = formatStr; serializationList.forEach((item) => { const itemKey = Object.keys(item)[0]; if (result.includes(itemKey)) { result = result.replace(itemKey, item[itemKey]); } }); return result; }; const getNum = (value, format, regx) => { let len = value.length; let formatStr = ""; if (format && regx) { const formatMatchArr = format.match(regx); formatStr = formatMatchArr.join(""); len = Math.max(len, formatStr.length); } const num = { str: "", arr: [] }; for (let i = 0; i < len; i++) { let fillStr = "0"; if (formatStr && len > value.length) { const validStr = getEffectiveDateString(formatStr); if (/[0-9]/.test(validStr[i])) { fillStr = validStr[i]; } } const char = value.charAt(i) ? value.charAt(i) : fillStr; if (/[0-9]/.test(char)) { num.str += char; } else { num.arr[i] = 1; } } return num; }; const getSelectionStartIndex = (event) => { const inputElem = event.target; return inputElem.selectionStart - (event.data ? event.data.length : 0); }; const moveStart = (inputElem, moveStartIndex) => { if (inputElem.setSelectionRange) { inputElem.focus(); setTimeout(() => { inputElem.setSelectionRange(moveStartIndex, moveStartIndex); }, 0); } }; const formatText = ({ event, text, format, needSelectionStart = false }) => { if (!format) return text; let cursorOffset = 0; let value = ""; let regx = /yyyy|yyy|yy|y|MM|M|dd|d|HH|hh|H|h|mm|m|ss|s|WW|W|w/g; let startIndex = 0; let { numStr, selectionStart } = getNumAndSelectionStart({ value: text, format, regx, event, needSelectionStart }); let matchResult = regx.exec(format); while (numStr.str !== "" && matchResult !== null) { let subStr; let newNum; let subLen; const endIndex = matchResult.index; if (startIndex >= 0) { value += format.substring(startIndex, endIndex); } selectionStart >= startIndex + cursorOffset && selectionStart <= endIndex + cursorOffset && (selectionStart = selectionStart + endIndex - startIndex); startIndex = regx.lastIndex; subLen = startIndex - endIndex; subStr = numStr.str.substring(0, subLen); const firstMatchChar = matchResult[0].charAt(0); const firstChar = parseInt(subStr.charAt(0), 10); if (numStr.str.length > 1) { const secondChar = numStr.str.charAt(1); newNum = 10 * firstChar + parseInt(secondChar, 10); } else { newNum = firstChar; } if (numStr.arr[endIndex + 1] || firstMatchChar === "M" && newNum > 12 || firstMatchChar === "d" && newNum > 31 || ["H", "h"].includes(firstMatchChar) && newNum > 23 || "ms".includes(firstMatchChar) && newNum > 59) { subStr = matchResult[0].length === 2 ? "0" + firstChar : firstChar; selectionStart++; } else { if (subLen === 1) { subStr = String(newNum); subLen++; cursorOffset++; } } value += subStr; numStr.str = numStr.str.substring(subLen); matchResult = regx.exec(format); } const { value: val, selectionStart: cursorPos } = checkFormat({ value, format, startIndex, selectionStart, regx, needSelectionStart }); value = val; selectionStart = cursorPos; needSelectionStart && moveStart(event.target, selectionStart); return value; }; const getNumAndSelectionStart = ({ value, format, regx, event, needSelectionStart }) => { if (needSelectionStart) { let { selectionStart, I } = getSelectionStart({ value, format, regx, event }); let valueStr; if (event.data) { valueStr = value.substring(0, selectionStart) + event.data + value.substring(selectionStart + I); selectionStart++; } else { valueStr = value; } const numStr = getNum(valueStr); return { numStr, selectionStart }; } else { const numStr = getNum(value, format, regx); return { numStr }; } }; const checkFormat = ({ value, format, startIndex, selectionStart, regx, needSelectionStart }) => { if (!needSelectionStart && regx.lastIndex === 0 || needSelectionStart && regx.lastIndex === 0 && selectionStart >= startIndex) { const subFormat = `(?<=${format.substring(0, startIndex)})(\\s*\\S*\\s*)+`; const pattern = new RegExp(subFormat, "g"); const res = format.match(pattern); if (res) { value += res[0]; selectionStart = value.length; } } return { value, selectionStart }; }; const handleChange = ({ api, state }) => () => { if (state.userInput) { const value = api.parseString(state.displayValue); if (value) { state.picker.state.value = value; if (api.isValidValue(value)) { api.emitInput(value); state.userInput = null; } } } if (state.userInput === "") { api.emitInput(null); api.emitChange(null); state.userInput = null; } }; const handleStartInput = ({ state, props, api }) => (event) => { const value = props.autoFormat ? api.formatInputValue({ event, prevValue: state.displayValue[0] }) : event.target.value; if (state.userInput) { state.userInput = [value, state.userInput[1]]; } else { state.userInput = [value, null]; } }; const handleEndInput = ({ state, props, api }) => (event) => { const value = props.autoFormat ? api.formatInputValue({ event, prevValue: state.displayValue[1] }) : event.target.value; if (state.userInput) { state.userInput = [state.userInput[0], value]; } else { state.userInput = [null, value]; } }; const handleStartChange = ({ api, state }) => () => { const value = api.parseString(state.userInput && state.userInput[0]); if (value) { let newValue; if (state.displayValue[1]) { state.userInput = [api.formatToString(value), state.displayValue[1]]; newValue = [value, state.picker.state.value && state.picker.state.value[1]]; state.startStatus = true; } else { let now = /* @__PURE__ */ new Date(); if (now.getTime() < value.getTime()) { state.userInput = [api.formatToString(value), api.formatToString(value)]; newValue = [value, value]; } else { state.userInput = [api.formatToString(value), ""]; newValue = [value, ""]; } } if (api.isValidValue(newValue)) { state.picker.state.value = newValue; state.historyUserInput = [value, state.picker.state.value && state.picker.state.value[1]]; state.historyUserValue = newValue; api.emitInput(newValue); state.userInput = null; } else { if (state.startStatus) { state.picker.state.value = state.historyUserValue ? state.historyUserValue : state.historyValue; api.emitInput(state.historyUserValue ? state.historyUserValue : state.historyValue); state.userInput = state.historyUserInput ? state.historyUserInput : state.historyInput; } else { state.picker.state.value = newValue; } } } }; const handleEndChange = ({ api, state }) => () => { const value = api.parseString(state.userInput && state.userInput[1]); if (value) { let newValue; if (state.displayValue[0]) { state.userInput = [state.displayValue[0], api.formatToString(value)]; newValue = [state.picker.state.value && state.picker.state.value[0], value]; state.endStatus = true; } else { let now = /* @__PURE__ */ new Date(); if (now.getTime() < value.getTime()) { state.userInput = [api.formatToString(now), api.formatToString(value)]; newValue = [now, value]; } else { state.userInput = [api.formatToString(value), api.formatToString(value)]; newValue = [value, value]; } } if (api.isValidValue(newValue)) { state.historyValue = newValue; state.historyInput = [state.displayValue[0], api.formatToString(value)]; state.picker.state.value = newValue; api.emitInput(newValue); state.userInput = null; } else { if (state.endStatus) { state.picker.state.value = state.historyValue; api.emitInput(state.historyValue); state.userInput = state.historyInput; } else { state.picker.state.value = state.historyValue; state.userInput = state.historyInput; } } } }; const handleClickIcon = ({ api, props, state }) => (event) => { if (props.readonly || state.pickerDisabled) { return; } if (state.showClose) { state.valueOnOpen = props.modelValue; event.stopPropagation(); api.emitInput(null); api.emitChange(null); state.showClose = false; if (state.picker && typeof state.picker.handleClear === "function") { state.picker.handleClear(); } } else { state.pickerVisible = !state.pickerVisible; } }; const handleClose = ({ api, props, state }) => () => { if (!state.pickerVisible) { return; } state.pickerVisible = false; if (state.type === DATEPICKER.Dates) { const oldValue = api.parseAsFormatAndType(state.valueOnOpen, state.valueFormat, state.type, props.rangeSeparator) || state.valueOnOpen; api.emitInput(oldValue, true); } }; const handleFocus = ({ emit, vm, state, api, props, isPCMode }) => () => { const type = state.type; if (props.readonly || state.pickerDisabled) { return; } if (DATEPICKER.TriggerTypes.includes(type)) { if (!state.isMobileScreen || isPCMode) { state.pickerVisible = true; } else if (state.isDateMobileComponent) { api.dateMobileToggle(true); } else if (state.isTimeMobileComponent) { api.timeMobileToggle(true); } } emit("focus", vm.$refs.reference); }; const handleKeydown = ({ api, state }) => (event) => { const keyCode = event.keyCode; if (keyCode === 27) { state.pickerVisible = false; event.stopPropagation(); return; } if (keyCode === 9) { if (!state.ranged) { api.handleChange(); state.pickerVisible = state.picker.state.visible = false; api.blur(); event.stopPropagation(); } else { setTimeout(() => { if (!state.refInput.includes(document.activeElement)) { state.pickerVisible = false; api.blur(); event.stopPropagation(); } }, 0); } return; } if (keyCode === 13) { if (state.userInput === "" || api.isValidValue(api.parseString(state.displayValue))) { if (state.type === "time-select") { state.userInput = state.picker.state.items.length ? state.picker.state.items[0].value : ""; } api.handleChange(); state.pickerVisible = state.picker.state.visible = false; api.blur(); } event.stopPropagation(); return; } if (state.userInput) { event.stopPropagation(); return; } if (state.picker && state.picker.handleKeydown) { state.picker.handleKeydown(event); } }; const hidePicker = ({ destroyPopper, state }) => () => { if (state.picker) { if (state.type === "time-select") { state.picker.state.isFilter = false; } state.picker.resetView && state.picker.resetView(); state.pickerVisible = state.picker.visible = state.picker.state.visible = false; destroyPopper(); } }; const showPicker = ({ api, nextTick, updatePopper, state }) => () => { if (!state.picker) { api.mountPicker(); } state.pickerVisible = state.picker.state.visible = true; state.picker.state.value = state.parsedValue; state.picker.resetView && state.picker.resetView(); nextTick(() => { updatePopper(state.picker.$el); state.picker.adjustSpinners && state.picker.adjustSpinners(); }); }; const handlePick = ({ state, api }) => (date = "", visible = false, chooseOne = false) => { if (!state.picker) return; if (chooseOne) { const minDate = date && date[0] || ""; state.userInput = [api.formatToString(minDate), null]; } else { state.userInput = null; state.pickerVisible = state.picker.state.visible = visible; api.emitInput(date, visible); state.date = date; state.picker.resetView && state.picker.resetView(); } }; const handleSelectRange = (state) => (start, end, pos) => { if (state.refInput.length === 0) { return; } const adjust = (value, start2, end2) => { if (value) { const valueReg = /(\d+):(\d+):(\d+)(\s+.+)?/; if (valueReg.test(value)) { const matched = valueReg.exec(value); const hourLength = matched[1].length; const minuteLength = matched[2].length; const secondLength = matched[3].length; if (start2 === 0) { end2 = hourLength; } else if (start2 === 3) { start2 = hourLength + 1; end2 = hourLength + minuteLength + 1; } else { start2 = hourLength + minuteLength + 2; end2 = hourLength + minuteLength + secondLength + 2; } } } return { start: start2, end: end2 }; }; if (!pos || pos === "min") { const value = state.refInput[0].value; const res = adjust(value, start, end); state.refInput[0].setSelectionRange(res.start, res.end); state.refInput[0].focus(); } else if (pos === "max") { const value = state.refInput[1].value; const res = adjust(value, start, end); state.refInput[1].setSelectionRange(res.start, res.end); state.refInput[1].focus(); } }; const mountPicker = ({ api, props, state, vm, updatePopper }) => () => { state.picker = vm.$refs.picker; state.picker.state.defaultValue = props.defaultValue; state.picker.state.defaultTime = props.defaultTime; state.picker.state.popperClass = props.popperClass; state.picker.state.popperAppendToBody = props.popperAppendToBody; state.picker.state.fnUpdatePopper = updatePopper; state.picker.state.currentInstans = state.picker; state.picker.state.timezone = state.timezone; state.picker.state.timezoneData = state.timezoneData; state.picker.state.showTimezone = props.showTimezone || state.timezone.isServiceTimezone; state.picker.state.width = state.reference.getBoundingClientRect().width; state.picker.state.timefmt = props.timeFormat || ""; state.picker.state.showTime = state.type === DATEPICKER.DateTime || state.type === DATEPICKER.DateTimeRange; state.picker.state.selectionMode = state.selectionMode; state.picker.state.defaultTimezone = props.defaultTimezone; state.picker.state.unlinkPanels = props.unlinkPanels; state.picker.state.emitDbTime = api.emitDbTime; state.picker.state.arrowControl = state.arrowControl || props.timeArrowControl || props.arrowControl || false; api.updateOptions(); state.picker.resetView && state.picker.resetView(); }; const updateOptions = ({ api, props, state }) => () => { if (!state.picker) { return; } const options = props.pickerOptions; if (options && options.selectableRange) { let ranges = options.selectableRange; const parser = api.typeValueResolveMap().datetimerange.parser; const format = DATEPICKER.DateFormats.timerange; ranges = Array.isArray(ranges) ? ranges : [ranges]; state.picker.state.selectableRange = ranges.map((range) => parser(range, format, props.rangeSeparator)); } for (const option in options) { if (option in options && option !== DATEPICKER.SelectbaleRange) { state.picker.state[option] = options[option]; } } if (props.format) { state.picker.state.format = props.format; } }; const valueEquals = (left, right) => { const dateEquals = (a, b) => { const bIsDate = b instanceof Date; const aIsDate = a instanceof Date; if (aIsDate && bIsDate) { return a.getTime() === b.getTime(); } if (!aIsDate && !bIsDate) { return a === b; } return false; }; const aIsArray = Array.isArray(left); const bIsArray = Array.isArray(right); if (aIsArray && bIsArray) { if (left.length !== right.length) { return false; } return left.every((item, index) => dateEquals(item, right[index])); } if (!aIsArray && !bIsArray) { return dateEquals(left, right); } return false; }; const emitChange = ({ api, dispatch, emit, props, state }) => (val) => { if (!valueEquals(val, state.valueOnOpen)) { emit("change", val); state.valueOnOpen = val; if (props.validateEvent) { dispatch("FormItem", "form.change", val); } api.emitDbTime(props.value); } }; const emitInput = ({ api, emit, props, state }) => (val, visible = false) => { let value = val; const { from, to, timezoneOffset } = state.timezone; if (props.type === "datetime") { value = getDateWithNewTimezone(value, to, from, -timezoneOffset); } else if (props.type === "datetimerange" && Array.isArray(value)) { value = value.map((val2) => getDateWithNewTimezone(val2, to, from, -timezoneOffset)); } const formatted = api.formatToValue(value) || val; if (!valueEquals(props.modelValue, formatted)) { emit("update:modelValue", formatted); } if (!visible && !valueEquals(state.oldValue, formatted)) { state.oldValue = formatted; } }; const isValidValue = ({ api, state }) => (value) => { if (!state.picker) { api.mountPicker(); } if (state.picker.isValidValue) { return value && state.picker.isValidValue(value); } return true; }; const watchIsRange = ({ api, state, TimePanel, TimeRangePanel }) => (value) => { state.type = value ? DATEPICKER.TimeRange : DATEPICKER.Time; state.panel = value ? TimeRangePanel : TimePanel; api.mountPicker(); }; const getType = ({ parent, props }) => () => { if (parent.componentName === DATEPICKER.DatePicker) { return props.type; } else if (parent.componentName === DATEPICKER.TimePicker) { return props.isRange ? DATEPICKER.TimeRange : DATEPICKER.Time; } return DATEPICKER.TimeSelect; }; const watchModelValue = ({ api, props, state, dispatch }) => (value, oldValue) => { state.historyInput = state.displayValue; if (state.picker) { state.historyValue = [ state.picker.state.value && state.picker.state.value[0], api.parseString(state.historyInput && state.historyInput[1]) ]; } if (props.changeCompat) { api.emitChange(props.modelValue); } if (!valueEquals(value, oldValue) && !state.pickerVisible && props.validateEvent) { dispatch("FormItem", "form.change", value); } }; const computedFormat = ({ props, utils }) => () => { let { type, format } = props; if (!format && utils.getDateFormat) { const config = utils.getDateFormat() || {}; if (~["date", "dates", "daterange"].indexOf(type)) { format = config.DateFormat; } if (~["datetime", "datetimerange"].indexOf(type)) { format = config.DateTimeFormat; } } return format; }; const computedTriggerClass = ({ props, state }) => () => { return props.suffixIcon || props.prefixIcon || (state.type.includes(DATEPICKER.Time) ? DATEPICKER.IconTime : DATEPICKER.IconDate); }; const computedHaveTrigger = ({ props }) => () => { return typeof props.showTrigger !== "undefined" ? props.showTrigger : DATEPICKER.TriggerTypes.includes(props.type); }; const initPopper = ({ props, hooks, vnode }) => { const { reactive, watch, toRefs, onBeforeUnmount, onDeactivated } = hooks; const { emit, vm, slots, nextTick } = vnode; const placementMap = DATEPICKER.PlacementMap; return userPopper({ reactive, watch, emit, props: __spreadProps(__spreadValues({}, props), { popperOptions: Object.assign({ boundariesPadding: 0, gpuAcceleration: false }, props.popperOptions), visibleArrow: false, offset: 0, boundariesPadding: 5, arrowOffset: 35, placement: placementMap[props.align] || placementMap.left }), toRefs, vm, slots, nextTick, onBeforeUnmount, onDeactivated }); }; const emitDbTime = ({ emit, state, t }) => (date) => { const { isServiceTimezone, from } = state.timezone; if (isServiceTimezone && !valueEquals(date, state.dbTime)) { let hasDate = false; const dbTime = [].concat(date).map((item) => { if (isDate(item)) { hasDate = true; let currentDate = getDateWithNewTimezone(item, getLocalTimezone(), from); if (state.valueFormat) { currentDate = formatDate(currentDate, state.valueFormat, t); } return currentDate; } return item; }); state.dbTime = dbTime.length > 1 ? dbTime : dbTime[0]; hasDate && emit("input", state.dbTime); } }; const initGlobalTimezone = ({ api, state, props }) => () => { const { isServiceTimezone } = state.timezone; if (isServiceTimezone) { state.timezoneData = globalTimezone; } else if (props.showTimezone) { state.timezoneData = props.timezoneData ? extend(true, {}, props.timezoneData) : globalTimezone; } api.emitDbTime(props.value); }; const handleEnterDisplayOnlyContent = ({ state, t }) => ($event) => { const target = $event.target; if (target && target.scrollWidth > target.offsetWidth) { state.displayOnlyTooltip = state.displayValue.join(` ${t("ui.datepicker.to")} `); } }; const handleEnterPickerlabel = ({ state, props }) => ($event) => { const target = $event.target; if (target && target.scrollWidth > target.offsetWidth) { state.labelTooltip = props.label; } }; const setInputPaddingLeft = ({ props, state, vm, nextTick }) => () => { const ml = 12; const mr = 8; if (props.label && !state.ranged && vm.$refs.label && vm.$refs.reference) { nextTick(() => { vm.$refs.reference.querySelector("input").style.paddingLeft = vm.$refs.label.offsetWidth + ml + mr + "px"; }); } }; export { blur, computedFormat, computedHaveTrigger, computedTriggerClass, dateFormatter, dateParser, displayValue, emitChange, emitDbTime, emitInput, firstInputId, focus, formatAsFormatAndType, formatInputValue, formatText, formatToString, formatToValue, getMode, getPanel, getTimezone, getType, getValueEmpty, getValueFormat, getWeekData, handleChange, handleClickIcon, handleClose, handleEndChange, handleEndInput, handleEnterDisplayOnlyContent, handleEnterPickerlabel, handleFocus, handleInput, handleKeydown, handleMouseEnter, handlePick, handleSelectRange, handleStartChange, handleStartInput, hidePicker, initGlobalTimezone, initPopper, isValidValue, mountPicker, parseAsFormatAndType, parseString, parseValue, parsedValue, rangeFormatter, rangeParser, secondInputId, setInputPaddingLeft, showPicker, typeValueResolveMap, updateOptions, valueEquals, watchIsRange, watchMobileVisible, watchModelValue, watchPickerVisible };