@opensig/opendesign
Version:
351 lines (350 loc) • 13.2 kB
JavaScript
;
const vue = require("vue");
const core = require("@vueuse/core");
const dayjs = require("dayjs");
const InBox_vue_vue_type_script_setup_true_lang = require("../_components/in-box/InBox.vue.js");
const InInput_vue_vue_type_script_setup_true_lang = require("../_components/in-input/InInput.vue.js");
const vueUtils = require("../_utils/vue-utils.js");
const useFormField = require("../_composables/use-form-field.js");
require("../_utils/is.js");
require("../hooks/use-theme.js");
const useScreen = require("../hooks/use-screen.js");
const index = require("../locale/index.js");
const icons = require("../_utils/icons.js");
const useClickOutside = require("../date-picker/composables/use-click-outside.js");
const types = require("./types.js");
const provide = require("./provide.js");
const useTimePickerOptions = require("./use-time-picker-options.js");
const findNearestTime = require("./find-nearest-time.js");
const useTimeRangeInputValidation = require("./use-time-range-input-validation.js");
const TimePanel_vue_vue_type_script_setup_true_lang = require("./components/TimePanel.vue.js");
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
__name: "OTimePicker",
props: /* @__PURE__ */ vue.mergeModels(types.timePickerProps, {
"modelValue": { default: void 0 },
"modelModifiers": {}
}),
emits: /* @__PURE__ */ vue.mergeModels(["change", "blur", "focus", "clear", "pressEnter"], ["update:modelValue"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const modelValue = vue.useModel(__props, "modelValue");
const {
effectiveColor: color,
inputId,
isFocus,
onFocus: formOnFocus,
onBlur: formOnBlur,
onClear: formOnClear,
onPressEnter: formOnPressEnter,
notifyChange
} = useFormField.useFormField(props, emits);
const propsRefs = vue.toRefs(props);
const { format, hourStep, minuteStep, secondStep, disabled, readonly, noResponsive } = propsRefs;
const { t } = index.useI18n();
const { isPhonePad } = useScreen.useScreen();
const isResponding = vue.computed(() => !(noResponsive == null ? void 0 : noResponsive.value) && isPhonePad.value);
const inBoxRef = vue.ref();
const inInputRef = vue.ref();
const panelRef = vue.ref();
const tempInputValue = vue.ref();
const tempParsed = vue.computed(() => {
var _a;
const [hour, minute, second] = ((_a = tempInputValue.value) == null ? void 0 : _a.split(":").map((v) => Number.parseInt(v))) ?? [];
return { hour, minute, second };
});
const tempSelectedHour = vue.computed(() => Number.isNaN(tempParsed.value.hour) ? null : tempParsed.value.hour);
const tempSelectedMinute = vue.computed(() => Number.isNaN(tempParsed.value.minute) ? null : tempParsed.value.minute);
const { hourOptions, minuteOptions, secondOptions, disabledHourOptions, disabledMinuteOptions, disabledSecondOptions } = useTimePickerOptions.useTimePickerOptions({
hourStep,
minuteStep,
secondStep,
disabledHours: propsRefs.disabledHours,
disabledMinutes: propsRefs.disabledMinutes,
disabledSeconds: propsRefs.disabledSeconds,
minTime: propsRefs.minTime,
maxTime: propsRefs.maxTime,
selectedHour: tempSelectedHour,
selectedMinute: tempSelectedMinute
});
vue.provide(provide.timePickerInjectKey, {
...propsRefs,
computedOptions: { hourOptions, minuteOptions, secondOptions, disabledHourOptions }
});
const isTempInputValueValid = vue.computed(() => {
const { hour, minute, second } = tempParsed.value;
if (!useTimeRangeInputValidation.isValidTimeUnit(hour, hourOptions.value, disabledHourOptions.value)) return false;
if (!useTimeRangeInputValidation.isValidTimeUnit(minute, minuteOptions.value, disabledMinuteOptions.value)) return false;
if (!useTimeRangeInputValidation.isValidTimeUnit(second, secondOptions.value, disabledSecondOptions.value)) return false;
return true;
});
vue.watch(
modelValue,
(newValue) => {
tempInputValue.value = newValue ?? "";
},
{ immediate: true }
);
vue.watch(isFocus, (newVal, oldVal) => {
var _a;
if (!newVal && oldVal) {
tempInputValue.value = modelValue.value ?? "";
if (!isResponding.value) {
(_a = panelRef.value) == null ? void 0 : _a.close();
}
}
});
useClickOutside.useClickOutside({
targets: [() => {
var _a;
return (_a = inBoxRef.value) == null ? void 0 : _a.$el;
}, () => {
var _a;
return (_a = panelRef.value) == null ? void 0 : _a.getPopupEl();
}],
onOutside: () => {
formOnBlur();
},
disabled: isResponding
});
const getNearestAvailableTime = () => {
const now = dayjs();
return findNearestTime.findNearestTime({
hourOptions: hourOptions.value,
minuteOptions: minuteOptions.value,
secondOptions: secondOptions.value,
minTime: props.minTime,
maxTime: props.maxTime,
disabledHours: props.disabledHours,
disabledMinutes: props.disabledMinutes,
disabledSeconds: props.disabledSeconds,
target: { hour: now.hour(), minute: now.minute(), second: now.second() },
format: format.value
});
};
let skipOpenPanel = false;
const onFocus = (e) => {
var _a;
if (readonly.value) return;
if (!skipOpenPanel) {
let valueToOpen = tempInputValue.value;
if (!valueToOpen) {
const nearest = getNearestAvailableTime();
if (nearest) {
tempInputValue.value = nearest;
valueToOpen = nearest;
}
}
(_a = panelRef.value) == null ? void 0 : _a.open(valueToOpen);
}
skipOpenPanel = false;
if (isFocus.value) return;
formOnFocus(e);
};
let prevValue = modelValue.value;
let internalChangePending = false;
vue.watch(modelValue, (_, old) => {
if (internalChangePending) {
internalChangePending = false;
} else {
prevValue = old;
}
});
const handleChange = () => {
var _a;
internalChangePending = true;
modelValue.value = isTempInputValueValid.value ? tempInputValue.value : (_a = panelRef.value) == null ? void 0 : _a.getValue();
emits("change", modelValue.value, prevValue);
prevValue = modelValue.value;
notifyChange();
};
const handleInput = core.useDebounceFn(async () => {
var _a;
await vue.nextTick();
if (isTempInputValueValid.value) {
(_a = panelRef.value) == null ? void 0 : _a.setValue(tempInputValue.value);
}
});
const blurAndClose = () => {
var _a, _b;
(_a = inInputRef.value) == null ? void 0 : _a.blur();
(_b = panelRef.value) == null ? void 0 : _b.close();
formOnBlur();
};
const cancelEdit = () => {
tempInputValue.value = modelValue.value ?? "";
blurAndClose();
};
const handlePanelChange = (newVal) => {
tempInputValue.value = newVal;
};
const onPressEnter = () => {
if (!isTempInputValueValid.value) {
cancelEdit();
return;
}
handleChange();
blurAndClose();
formOnPressEnter();
};
const handleConfirm = () => {
handleChange();
formOnBlur();
formOnPressEnter();
};
const handleCancel = () => {
cancelEdit();
};
const onClear = (e) => {
e == null ? void 0 : e.stopPropagation();
const oldVal = prevValue;
internalChangePending = true;
modelValue.value = void 0;
tempInputValue.value = "";
prevValue = void 0;
emits("change", void 0, oldVal);
formOnClear(e);
notifyChange();
blurAndClose();
};
__expose({
/**
* @zh-CN 使输入框获取焦点,open 为 false 时仅聚焦不打开面板
* @en-US Focus the input. Pass false to focus without opening the panel.
*/
focus: (open = true) => {
var _a;
if (!open) skipOpenPanel = true;
(_a = inInputRef.value) == null ? void 0 : _a.focus();
},
/**
* @zh-CN 使输入框失去焦点,校验合法则应用当前值,否则回滚
* @en-US Blur the input. Applies the current value if valid, otherwise rolls back.
*/
blur: () => {
if (isTempInputValueValid.value) {
handleChange();
blurAndClose();
} else {
cancelEdit();
}
},
/**
* @zh-CN 清除输入值
* @en-US Clear the input value
*/
clear: () => {
var _a;
return (_a = inInputRef.value) == null ? void 0 : _a.clear();
},
/**
* @zh-CN 获取输入框 DOM 元素
* @en-US Get the input DOM element
*/
inputEl: () => {
var _a;
return (_a = inInputRef.value) == null ? void 0 : _a.inputEl;
}
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createBlock(
vue.unref(InBox_vue_vue_type_script_setup_true_lang),
vue.mergeProps({
ref_key: "inBoxRef",
ref: inBoxRef
}, {
size: props.size,
variant: props.variant,
color: vue.unref(color),
disabled: props.disabled,
readonly: props.readonly,
round: props.round,
focused: vue.unref(isFocus)
}, { class: ["o-time-picker", "o-input"] }),
vue.createSlots({
default: vue.withCtx(() => {
var _a;
return [
vue.createVNode(vue.unref(InInput_vue_vue_type_script_setup_true_lang), {
ref_key: "inInputRef",
ref: inInputRef,
modelValue: tempInputValue.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => tempInputValue.value = $event),
class: vue.normalizeClass(["o-input-wrap", { "o-input-wrap-focused": vue.unref(isFocus), "o-input-wrap-touch": isResponding.value }]),
disabled: vue.unref(disabled),
clearable: props.clearable && !!tempInputValue.value,
placeholder: props.placeholder ?? vue.unref(t)("timePicker.placeholder"),
"input-id": vue.unref(inputId),
"max-length": ((_a = vue.unref(format)) == null ? void 0 : _a.length) ?? 8,
"input-on-outlimit": false,
"show-length": "never",
readonly: vue.unref(readonly),
"no-keyboard": "",
onKeydown: vue.withKeys(handleCancel, ["esc"]),
onInput: vue.unref(handleInput),
onFocus,
onClear,
onPressEnter
}, vue.createSlots({
extra: vue.withCtx(() => {
var _a2;
return [
!vue.unref(disabled) && !vue.unref(readonly) ? (vue.openBlock(), vue.createBlock(TimePanel_vue_vue_type_script_setup_true_lang, {
key: 0,
ref_key: "panelRef",
ref: panelRef,
target: (_a2 = inBoxRef.value) == null ? void 0 : _a2.$el,
"option-title": props.optionTitle,
onChange: handlePanelChange,
onCancel: handleCancel,
onConfirm: handleConfirm
}, {
shortcut: vue.withCtx(({ setValue: panelSetValue, emitChange }) => [
vue.renderSlot(_ctx.$slots, "shortcut", {
setValue: panelSetValue,
emitChange
})
]),
_: 3
/* FORWARDED */
}, 8, ["target", "option-title"])) : vue.createCommentVNode("v-if", true)
];
}),
_: 2
/* DYNAMIC */
}, [
!isResponding.value || !tempInputValue.value ? {
name: "suffix",
fn: vue.withCtx(() => [
vue.createVNode(vue.unref(icons.IconTime))
]),
key: "0"
} : void 0
]), 1032, ["modelValue", "class", "disabled", "clearable", "placeholder", "input-id", "max-length", "readonly", "onInput"])
];
}),
_: 2
/* DYNAMIC */
}, [
!vue.unref(vueUtils.isEmptySlot)(_ctx.$slots.prepend) ? {
name: "prepend",
fn: vue.withCtx(() => [
vue.renderSlot(_ctx.$slots, "prepend")
]),
key: "0"
} : void 0,
!vue.unref(vueUtils.isEmptySlot)(_ctx.$slots.append) ? {
name: "append",
fn: vue.withCtx(() => [
vue.renderSlot(_ctx.$slots, "append")
]),
key: "1"
} : void 0
]),
1040
/* FULL_PROPS, DYNAMIC_SLOTS */
);
};
}
});
module.exports = _sfc_main;