UNPKG

@opensig/opendesign

Version:

471 lines (470 loc) 17.5 kB
"use strict"; 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;