@opensig/opendesign
Version:
299 lines (298 loc) • 9.78 kB
JavaScript
;
const vue = require("vue");
const index = require("../popover/index.js");
const keycode = require("../_utils/keycode.js");
const vueUtils = require("../_utils/vue-utils.js");
const provide = require("./provide.js");
const types = require("./types.js");
const _hoisted_1 = ["tabindex"];
const _hoisted_2 = {
key: 0,
class: "o-slider-circle"
};
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
__name: "OSliderButton",
props: types.sliderButtonProps,
emits: ["update:modelValue"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const initData = vue.reactive({
hovering: false,
dragging: false,
isClick: false,
startX: 0,
currentX: 0,
startY: 0,
currentY: 0,
startPosition: 0,
newPosition: 0,
oldValue: props.modelValue
});
const { disabled, min, max, step, sliderSize, emitChange, resetSize, updateDragging } = vue.inject(provide.sliderInjectKey);
const button = vue.ref();
const { hovering, dragging } = vue.toRefs(initData);
const formatValue = vue.computed(() => {
return props.modelValue;
});
const showToolTip = vue.computed(() => {
return initData.hovering || initData.dragging;
});
const currentPosition = vue.computed(() => {
return `${(props.modelValue - min.value) / (max.value - min.value) * 100}%`;
});
const wrapperStyle = vue.computed(() => {
return { left: currentPosition.value };
});
const handleMouseEnter = () => {
initData.hovering = true;
};
const handleMouseLeave = () => {
initData.hovering = false;
};
const onButtonDown = (event) => {
if (disabled.value) {
return;
}
event.preventDefault();
handleDragStart(event);
window.addEventListener("mousemove", handleDragging);
window.addEventListener("touchmove", handleDragging);
window.addEventListener("mouseup", handleDragEnd);
window.addEventListener("touchend", handleDragEnd);
window.addEventListener("contextmenu", handleDragEnd);
button.value.focus();
};
const incrementPosition = (amount) => {
if (disabled.value) {
return;
}
initData.newPosition = Number.parseFloat(currentPosition.value) + amount / (max.value - min.value) * 100;
setPosition(initData.newPosition);
emitChange();
};
const onLeftKeyDown = () => {
incrementPosition(-step.value);
};
const onRightKeyDown = () => {
incrementPosition(step.value);
};
const onPageDownKeyDown = () => {
incrementPosition(-step.value * 4);
};
const onPageUpKeyDown = () => {
incrementPosition(step.value * 4);
};
const onHomeKeyDown = () => {
if (disabled.value) {
return;
}
setPosition(0);
emitChange();
};
const onEndKeyDown = () => {
if (disabled.value) {
return;
}
setPosition(100);
emitChange();
};
const onKeyDown = (event) => {
const code = event.code;
let isPreventDefault = true;
switch (code) {
case keycode.ArrowLeft.key:
case keycode.ArrowDown.key:
onLeftKeyDown();
break;
case keycode.ArrowRight.key:
case keycode.ArrowUp.key:
onRightKeyDown();
break;
case keycode.Home.key:
onHomeKeyDown();
break;
case keycode.End.key:
onEndKeyDown();
break;
case keycode.pageDown.key:
onPageDownKeyDown();
break;
case keycode.pageUp.key:
onPageUpKeyDown();
break;
default:
isPreventDefault = false;
break;
}
isPreventDefault && event.preventDefault();
};
const getClientXY = (event) => {
let clientX;
let clientY;
if (event.type.startsWith("touch")) {
clientY = event.touches[0].clientY;
clientX = event.touches[0].clientX;
} else {
clientY = event.clientY;
clientX = event.clientX;
}
return {
clientX,
clientY
};
};
const handleDragStart = (event) => {
initData.dragging = true;
initData.isClick = true;
const { clientX, clientY } = getClientXY(event);
if (props.direction === "v") {
initData.startY = clientY;
} else {
initData.startX = clientX;
}
initData.startPosition = Number.parseFloat(currentPosition.value);
initData.newPosition = initData.startPosition;
};
const handleDragging = (event) => {
if (initData.dragging) {
initData.isClick = false;
resetSize();
let diff;
const { clientX, clientY } = getClientXY(event);
if (props.direction === "v") {
initData.currentY = clientY;
diff = (initData.startY - initData.currentY) / sliderSize.value * 100;
} else {
initData.currentX = clientX;
diff = (initData.currentX - initData.startX) / sliderSize.value * 100;
}
initData.newPosition = initData.startPosition + diff;
setPosition(initData.newPosition);
}
};
const handleDragEnd = () => {
if (initData.dragging) {
setTimeout(() => {
initData.dragging = false;
if (!initData.isClick) {
setPosition(initData.newPosition);
}
emitChange();
}, 0);
window.removeEventListener("mousemove", handleDragging);
window.removeEventListener("touchmove", handleDragging);
window.removeEventListener("mouseup", handleDragEnd);
window.removeEventListener("touchend", handleDragEnd);
window.removeEventListener("contextmenu", handleDragEnd);
}
};
const clamp = (num, lower, upper) => {
return Math.max(lower, Math.min(num, upper));
};
const setPosition = async (newPosition) => {
if (newPosition === null || Number.isNaN(+newPosition)) {
return;
}
newPosition = clamp(newPosition, 0, 100);
const fullSteps = Math.floor((max.value - min.value) / step.value);
const fullRangePercentage = fullSteps * step.value / (max.value - min.value) * 100;
const threshold = fullRangePercentage + (100 - fullRangePercentage) / 2;
let value;
if (newPosition < fullRangePercentage) {
const valueBetween = fullRangePercentage / fullSteps;
const steps = Math.round(newPosition / valueBetween);
value = min.value + steps * step.value;
} else if (newPosition < threshold) {
value = min.value + fullSteps * step.value;
} else {
value = max.value;
}
value = Number.parseFloat(value.toFixed());
if (value !== props.modelValue) {
emit("update:modelValue", value);
}
if (!initData.dragging && props.modelValue !== initData.oldValue) {
initData.oldValue = props.modelValue;
}
};
vue.watch(
() => initData.dragging,
(val) => {
updateDragging(val);
}
);
vue.onMounted(() => {
var _a;
(_a = button.value) == null ? void 0 : _a.addEventListener("touchstart", onButtonDown, { passive: false });
});
vue.onUnmounted(() => {
var _a;
(_a = button.value) == null ? void 0 : _a.removeEventListener("touchstart", onButtonDown);
});
__expose({
onButtonDown,
onKeyDown,
setPosition,
hovering,
dragging
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock(
vue.Fragment,
null,
[
vue.createElementVNode("div", {
ref_key: "button",
ref: button,
class: vue.normalizeClass(["o-slider-btn-wrap", { "o-slider-btn-wrap-hover": showToolTip.value && !props.showSolidCircle && !vue.unref(disabled) }]),
style: vue.normalizeStyle(wrapperStyle.value),
tabindex: vue.unref(disabled) ? void 0 : 0,
onMouseenter: handleMouseEnter,
onMouseleave: handleMouseLeave,
onMousedown: onButtonDown,
onFocus: handleMouseEnter,
onBlur: handleMouseLeave,
onKeydown: onKeyDown
}, [
vue.createElementVNode(
"div",
{
class: vue.normalizeClass(["o-slider-btn", { "o-slider-btn-hover": showToolTip.value && !props.showSolidCircle && !vue.unref(disabled) }])
},
[
props.showSolidCircle ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2)) : vue.createCommentVNode("v-if", true)
],
2
/* CLASS */
)
], 46, _hoisted_1),
_ctx.showPopover ? (vue.openBlock(), vue.createBlock(vue.unref(index.OPopover), {
key: 0,
trigger: "none",
position: props.position,
visible: showToolTip.value && !vue.unref(disabled),
"adjust-width": false,
"adjust-min-width": false,
target: button.value,
wrapper: button.value,
"wrap-class": vue.unref(vueUtils.mergeClass)("o-slider-popover", props.wrapClass)
}, {
default: vue.withCtx(() => [
vue.createTextVNode(
vue.toDisplayString(formatValue.value),
1
/* TEXT */
)
]),
_: 1
/* STABLE */
}, 8, ["position", "visible", "target", "wrapper", "wrap-class"])) : vue.createCommentVNode("v-if", true)
],
64
/* STABLE_FRAGMENT */
);
};
}
});
module.exports = _sfc_main;