@opensig/opendesign
Version:
471 lines (470 loc) • 17.5 kB
JavaScript
;
const vue = require("vue");
const core = require("@vueuse/core");
const index = require("../locale/index.js");
const icons = require("../_utils/icons.js");
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 useFormField = require("../_composables/use-form-field.js");
const vueUtils = require("../_utils/vue-utils.js");
const keycode = require("../_utils/keycode.js");
const useClickOutside = require("../date-picker/composables/use-click-outside.js");
const types = require("./types.js");
const provide = require("./provide.js");
const TimeRangePanel_vue_vue_type_script_setup_true_lang = require("./components/TimeRangePanel.vue.js");
const useTimeRangeConstraints = require("./use-time-range-constraints.js");
const useTimeRangeInputValidation = require("./use-time-range-input-validation.js");
const _hoisted_1 = { class: "o_input-suffix-icon" };
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
__name: "OTimeRangePicker",
props: /* @__PURE__ */ vue.mergeModels(types.timeRangePickerProps, {
"start": { default: void 0, required: true },
"startModifiers": {},
"end": { default: void 0, required: true },
"endModifiers": {}
}),
emits: /* @__PURE__ */ vue.mergeModels(["change", "blur", "focus", "clear", "pressEnter"], ["update:start", "update:end"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const start = vue.useModel(__props, "start");
const end = vue.useModel(__props, "end");
const tempStart = vue.ref(start.value ?? "");
vue.watch(start, (newVal) => tempStart.value = newVal ?? "");
const tempEnd = vue.ref(end.value ?? "");
vue.watch(end, (newVal) => tempEnd.value = newVal ?? "");
const startFocused = vue.ref(false);
const endFocused = vue.ref(false);
const focused = vue.computed(() => startFocused.value || endFocused.value);
vue.watch(focused, (newVal, oldVal) => {
if (!newVal && oldVal) {
emits("blur");
}
});
const isClearable = vue.computed(() => props.clearable && !props.disabled && !props.readonly && (!!tempStart.value || !!tempEnd.value));
const { t } = index.useI18n();
const inBoxRef = vue.ref();
const startInputRef = vue.ref();
const endInputRef = vue.ref();
const panelRef = vue.ref();
const { maxStartTime, minEndTime } = useTimeRangeConstraints.useTimeRangeConstraints({
startTime: tempStart,
endTime: tempEnd,
format: vue.toRef(props, "format"),
hourStep: vue.toRef(props, "hourStep"),
minuteStep: vue.toRef(props, "minuteStep"),
secondStep: vue.toRef(props, "secondStep")
});
const { isStartValid, isEndValid } = useTimeRangeInputValidation.useTimeRangeInputValidation({
tempStart,
tempEnd,
format: vue.toRef(props, "format"),
hourStep: vue.toRef(props, "hourStep"),
minuteStep: vue.toRef(props, "minuteStep"),
secondStep: vue.toRef(props, "secondStep"),
minTime: vue.toRef(props, "minTime"),
maxTime: vue.toRef(props, "maxTime"),
maxStartTime,
minEndTime,
disabledHours: vue.toRef(props, "disabledHours"),
disabledMinutes: vue.toRef(props, "disabledMinutes"),
disabledSeconds: vue.toRef(props, "disabledSeconds")
});
vue.watch(
tempStart,
core.useDebounceFn(async () => {
var _a;
await vue.nextTick();
if (isStartValid.value && tempStart.value) (_a = panelRef.value) == null ? void 0 : _a.setStartValue(tempStart.value);
}, 300)
);
vue.watch(
tempEnd,
core.useDebounceFn(async () => {
var _a;
await vue.nextTick();
if (isEndValid.value && tempEnd.value) (_a = panelRef.value) == null ? void 0 : _a.setEndValue(tempEnd.value);
}, 300)
);
const { effectiveColor: color, inputId: startInputId, notifyChange } = useFormField.useFormField(props, emits);
let skipOpenPanel = false;
const openPanel = () => {
var _a;
if (props.disabled || props.readonly) return;
(_a = panelRef.value) == null ? void 0 : _a.open(tempStart.value || void 0, tempEnd.value || void 0);
};
const blurAndClose = () => {
var _a, _b, _c;
(_a = panelRef.value) == null ? void 0 : _a.close();
startFocused.value = false;
endFocused.value = false;
(_b = startInputRef.value) == null ? void 0 : _b.blur();
(_c = endInputRef.value) == null ? void 0 : _c.blur();
};
const cancelEdit = () => {
tempStart.value = start.value ?? "";
tempEnd.value = end.value ?? "";
blurAndClose();
};
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: cancelEdit
});
const onFocus = (e, rangeType) => {
if (!focused.value) {
emits("focus", e);
}
if (rangeType === "start") {
startFocused.value = true;
} else {
endFocused.value = true;
}
if (!skipOpenPanel) openPanel();
skipOpenPanel = false;
};
let prevRangeValue = { start: start.value, end: end.value };
let internalRangeChangePending = false;
vue.watch([start, end], ([_newStart, _newEnd], [oldStart, oldEnd]) => {
if (internalRangeChangePending) {
internalRangeChangePending = false;
} else {
prevRangeValue = { start: oldStart, end: oldEnd };
}
});
const onChange = () => {
const empty = !tempStart.value && !tempEnd.value;
const full = tempStart.value && tempEnd.value;
if (empty || full) {
const oldVal = prevRangeValue;
internalRangeChangePending = true;
start.value = tempStart.value;
end.value = tempEnd.value;
prevRangeValue = { start: start.value, end: end.value };
emits("change", prevRangeValue, oldVal);
notifyChange();
}
};
const confirmAndClose = () => {
onChange();
blurAndClose();
emits("pressEnter");
};
const onPanelChange = (startVal, endVal) => {
tempStart.value = startVal ?? "";
tempEnd.value = endVal ?? "";
};
const onPanelConfirm = (startVal, endVal) => {
tempStart.value = startVal ?? "";
tempEnd.value = endVal ?? "";
onChange();
startFocused.value = false;
endFocused.value = false;
};
const switchFocusTo = (targetRange) => {
const targetRef = targetRange === "start" ? startInputRef : endInputRef;
startFocused.value = targetRange === "start";
endFocused.value = targetRange === "end";
requestAnimationFrame(() => {
var _a;
return (_a = targetRef.value) == null ? void 0 : _a.focus();
});
};
const isCursorAtEdge = (inputRef, position) => {
var _a;
const inputEl = (_a = inputRef.value) == null ? void 0 : _a.inputEl;
if (!inputEl) return false;
const { selectionStart, selectionEnd, value } = inputEl;
return selectionStart === selectionEnd && (position === "start" ? selectionStart === 0 : selectionStart === value.length);
};
const handleTab = (e, rangeType) => {
const toEnd = rangeType === "start" && !e.shiftKey;
const toStart = rangeType === "end" && e.shiftKey;
if (toEnd || toStart) {
e.preventDefault();
switchFocusTo(
toEnd ? "end" : "start"
/* s */
);
} else {
const bothValid = isStartValid.value && isEndValid.value;
if (bothValid) confirmAndClose();
else cancelEdit();
}
};
const handleArrowRight = (e, rangeType) => {
if (rangeType === "start" && isCursorAtEdge(startInputRef, "end")) {
e.preventDefault();
switchFocusTo(
"end"
/* e */
);
}
};
const handleArrowLeft = (e, rangeType) => {
if (rangeType === "end" && isCursorAtEdge(endInputRef, "start")) {
e.preventDefault();
switchFocusTo(
"start"
/* s */
);
}
};
const keyHandlers = {
[keycode.Tab.key]: handleTab,
[keycode.ArrowRight.key]: handleArrowRight,
[keycode.ArrowLeft.key]: handleArrowLeft
};
const onKeydown = (e, rangeType) => {
var _a;
(_a = keyHandlers[e.key]) == null ? void 0 : _a.call(keyHandlers, e, rangeType);
};
const confirmOrSwitchFocus = (rangeType) => {
const bothValid = isStartValid.value && isEndValid.value;
if (rangeType === "start") {
if (!tempEnd.value) {
switchFocusTo(
"end"
/* e */
);
} else if (bothValid) {
confirmAndClose();
}
} else {
if (!tempStart.value) {
switchFocusTo(
"start"
/* s */
);
} else if (bothValid) {
confirmAndClose();
}
}
};
const onPressEnter = (rangeType) => {
if (rangeType === "start" && !isStartValid.value) {
cancelEdit();
return;
}
if (rangeType === "end" && !isEndValid.value) {
cancelEdit();
return;
}
confirmOrSwitchFocus(rangeType);
};
const onClear = () => {
const oldVal = prevRangeValue;
internalRangeChangePending = true;
start.value = void 0;
end.value = void 0;
tempStart.value = "";
tempEnd.value = "";
prevRangeValue = { start: void 0, end: void 0 };
emits("clear");
emits("change", prevRangeValue, oldVal);
notifyChange();
blurAndClose();
};
vue.provide(provide.timePickerInjectKey, {
...vue.toRefs(props),
isRange: vue.ref(true)
});
__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 = startInputRef.value) == null ? void 0 : _a.focus();
},
/**
* @zh-CN 使输入框失去焦点,校验合法则应用当前值,否则回滚
* @en-US Blur the input. Applies the current value if valid, otherwise rolls back.
*/
blur: () => {
if (isStartValid.value && isEndValid.value) {
confirmAndClose();
} else {
cancelEdit();
}
},
/**
* @zh-CN 清除输入值
* @en-US Clear the input value
*/
clear: () => onClear()
});
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: !!focused.value
}, {
class: ["o-time-picker", "o-time-range-picker", { "o_input-clearable": isClearable.value }, "o-input"]
}), vue.createSlots({
default: vue.withCtx(() => {
var _a, _b;
return [
vue.createVNode(vue.unref(InInput_vue_vue_type_script_setup_true_lang), {
ref_key: "startInputRef",
ref: startInputRef,
modelValue: tempStart.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => tempStart.value = $event),
class: vue.normalizeClass(["o-input-wrap o-range-start-input-wrap", { "o-input-wrap-focused": startFocused.value }]),
disabled: _ctx.disabled,
readonly: _ctx.readonly,
"input-id": vue.unref(startInputId),
placeholder: props.placeholderStart ?? vue.unref(t)("timePicker.startTime"),
"max-length": ((_a = props.format) == null ? void 0 : _a.length) ?? 8,
"input-on-outlimit": false,
"show-length": "never",
"no-keyboard": "",
onFocus: _cache[1] || (_cache[1] = (e) => onFocus(
e,
"start"
/* s */
)),
onKeydown: _cache[2] || (_cache[2] = (e) => onKeydown(
e,
"start"
/* s */
)),
onPressEnter: _cache[3] || (_cache[3] = () => onPressEnter(
"start"
/* s */
))
}, {
extra: vue.withCtx(() => {
var _a2;
return [
!_ctx.disabled && !_ctx.readonly ? (vue.openBlock(), vue.createBlock(TimeRangePanel_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: onPanelChange,
onConfirm: onPanelConfirm
}, vue.createSlots({
_: 2
/* DYNAMIC */
}, [
!vue.unref(vueUtils.isEmptySlot)(_ctx.$slots.shortcut) ? {
name: "shortcut",
fn: vue.withCtx(({ setValue, emitChange }) => [
vue.renderSlot(_ctx.$slots, "shortcut", {
setValue,
emitChange
})
]),
key: "0"
} : void 0
]), 1032, ["target", "option-title"])) : vue.createCommentVNode("v-if", true)
];
}),
_: 3
/* FORWARDED */
}, 8, ["modelValue", "class", "disabled", "readonly", "input-id", "placeholder", "max-length"]),
_cache[10] || (_cache[10] = vue.createElementVNode(
"div",
{ class: "o-time-range-picker-divider" },
"-",
-1
/* CACHED */
)),
vue.createVNode(vue.unref(InInput_vue_vue_type_script_setup_true_lang), {
ref_key: "endInputRef",
ref: endInputRef,
modelValue: tempEnd.value,
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => tempEnd.value = $event),
class: vue.normalizeClass(["o-input-wrap o-range-end-input-wrap", { "o-input-wrap-focused": endFocused.value }]),
disabled: _ctx.disabled,
readonly: _ctx.readonly,
placeholder: props.placeholderEnd ?? vue.unref(t)("timePicker.endTime"),
"max-length": ((_b = props.format) == null ? void 0 : _b.length) ?? 8,
"input-on-outlimit": false,
"show-length": "never",
"no-keyboard": "",
onFocus: _cache[5] || (_cache[5] = (e) => onFocus(
e,
"end"
/* e */
)),
onKeydown: _cache[6] || (_cache[6] = (e) => onKeydown(
e,
"end"
/* e */
)),
onPressEnter: _cache[7] || (_cache[7] = () => onPressEnter(
"end"
/* e */
))
}, null, 8, ["modelValue", "class", "disabled", "readonly", "placeholder", "max-length"]),
vue.createElementVNode(
"div",
{
class: "o_input-suffix",
onMousedown: _cache[9] || (_cache[9] = vue.withModifiers(() => {
}, ["prevent"]))
},
[
vue.createElementVNode("span", _hoisted_1, [
vue.createVNode(vue.unref(icons.IconTime))
]),
isClearable.value ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 0,
class: "o_input-clear",
onClick: onClear,
onMousedown: _cache[8] || (_cache[8] = vue.withModifiers(() => {
}, ["prevent"]))
},
[
vue.createVNode(vue.unref(icons.IconClose), { class: "o_input-clear-icon" })
],
32
/* NEED_HYDRATION */
)) : vue.createCommentVNode("v-if", true)
],
32
/* NEED_HYDRATION */
)
];
}),
_: 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, ["class"]);
};
}
});
module.exports = _sfc_main;