maz-ui
Version:
A standalone components library for Vue.Js 3 & Nuxt.Js 3
206 lines (205 loc) • 10.5 kB
JavaScript
import { defineComponent, ref, computed, watch, onMounted, onBeforeUnmount, nextTick, createElementBlock, openBlock, normalizeClass, normalizeStyle, createElementVNode, Fragment, renderList, toDisplayString } from "vue";
import { d as debounce } from "../chunks/debounce.Brzkn9pm.js";
import { _ as _export_sfc } from "../chunks/_plugin-vue_export-helper.B--vMWp3.js";
import '../assets/MazSlider.WcnBC9zc.css';function getOffset(elem) {
const doc = document.documentElement, body = document.body, rect = elem.getBoundingClientRect();
return {
y: rect.top + (window.pageYOffset || doc.scrollTop) - (doc.clientTop || body.clientTop || 0),
x: rect.left + (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || body.clientLeft || 0)
};
}
function getPos(e, elem, isReverse = !1) {
const event = "targetTouches" in e ? e.targetTouches[0] : e, offset = getOffset(elem), posObj = {
x: event.pageX - offset.x,
y: event.pageY - offset.y
};
return {
x: isReverse ? elem.offsetWidth - posObj.x : posObj.x,
y: isReverse ? elem.offsetHeight - posObj.y : posObj.y
};
}
function isBetween(value, prev, next, direction) {
return direction === "minus" ? prev ? value >= prev : !0 : next ? value <= next : !0;
}
function getOpacityCoeff(index, middle, length) {
const currentIndex = index + 1, deviation = middle < currentIndex ? currentIndex - middle : middle - currentIndex;
return 100 / length * deviation / 100;
}
const _hoisted_1 = ["aria-valuenow", "aria-valuemin", "aria-valuemax"], _hoisted_2 = ["data-label", "onMousedownPassive", "onTouchstartPassive", "onFocusPassive", "onBlurPassive", "onTouchendPassive", "onKeydownPassive"], _sfc_main = /* @__PURE__ */ defineComponent({
__name: "MazSlider",
props: {
modelValue: {},
labels: {},
min: { default: 0 },
max: { default: 100 },
step: { default: 1 },
size: {},
divider: { type: Boolean, default: !0 },
log: { type: Boolean, default: !1 },
color: { default: "primary" },
cursorAnim: { type: Boolean, default: !0 }
},
emits: ["update:model-value"],
setup(__props, { emit: __emit }) {
const emits = __emit, MazSlider2 = ref(), activeCursor = ref(), buttonPositions = ref(), tmpValues = ref(), buttonStyles = ref([]), dividers = ref([]), computedValue = computed(() => typeof __props.modelValue == "number" ? [__props.modelValue] : __props.modelValue ? __props.modelValue : [0]), minLog = computed(() => Math.log(__props.min || 1)), maxLog = computed(() => Math.log(__props.max)), scale = computed(() => (maxLog.value - minLog.value) / (__props.max - __props.min)), range = computed(() => __props.max - __props.min), wrapperStyle = computed(() => ({
paddingTop: __props.labels ? "2.5em" : "1em"
})), hasMultipleValues = computed(() => Array.isArray(__props.modelValue));
watch(
() => __props.modelValue,
() => tmpValues.value = computedValue.value,
{ immediate: !0 }
), watch(
() => [computedValue.value, __props.min, __props.max, __props.log].join(","),
() => buildComponent(!0)
);
const resizeListenerFunction = debounce(() => buildComponent(), 300);
onMounted(() => {
buildComponent(!0), window.addEventListener("resize", resizeListenerFunction);
}), onBeforeUnmount(() => {
window.removeEventListener("resize", resizeListenerFunction);
});
async function buildComponent(emitValue2) {
emitValue2 === !0 && checkValues(), await calcPos(), await nextTick();
for (const [index] of computedValue.value.entries())
setBtnDividers(index);
}
function roundToStep(value) {
return Math.round((value - __props.min) / __props.step) * __props.step + __props.min;
}
function cursorKeyDown(event, i) {
event.key === "ArrowLeft" ? tmpValues.value && isBetween(tmpValues.value[i] - __props.step, tmpValues.value[i - 1], tmpValues.value[i + 1], "minus") && (tmpValues.value[i] = Math.max(__props.min, tmpValues.value[i] - __props.step), emitValue(tmpValues.value)) : event.key === "ArrowRight" && tmpValues.value && isBetween(tmpValues.value[i] + __props.step, tmpValues.value[i - 1], tmpValues.value[i + 1], "plus") && (tmpValues.value[i] = Math.min(__props.max, tmpValues.value[i] + __props.step), emitValue(tmpValues.value));
}
function blurCursor(i) {
activeCursor.value = void 0, setBtnStyle(i);
}
function checkValues() {
const valuesChecked = computedValue.value.map((v) => {
const checkedValue = v < __props.min ? __props.min : v > __props.max ? __props.max : v;
return roundToStep(checkedValue);
});
emitValue(valuesChecked), tmpValues.value = valuesChecked;
}
function emitValue(values) {
const valueToEmit = hasMultipleValues.value ? [...values] : values[0];
emits("update:model-value", valueToEmit);
}
function getLabel(i) {
return __props.labels ? __props.labels[i] : void 0;
}
function setBtnDividers(i) {
setBtnStyle(i), __props.divider && setDividers();
}
async function setBtnStyle(i) {
await nextTick();
const currentCursor = document.querySelectorAll(".m-slider .m-slider__btn");
if (currentCursor) {
const width = currentCursor[i]?.clientWidth + 16, btnStyle = {
left: typeof buttonPositions.value?.[i] == "number" ? `${buttonPositions.value[i] - width / 2 || 1}px` : ""
};
buttonStyles.value[i] = btnStyle;
}
}
function setDividers() {
if (buttonPositions.value) {
const base = [...buttonPositions.value];
base.push(0);
const baseLength = base.length, middle = Math.round(baseLength / 2);
dividers.value = base.map((pos, i) => ({
left: i === 0 ? 0 : `${base[i - 1]}px`,
// ATTENTION: buttonPositions.value[i - 1]
right: i + 1 === baseLength ? 0 : `calc( 100% - ${pos}px )`,
backgroundColor: middle === i + 1 ? void 0 : i < middle ? `rgba(255, 255, 255, ${getOpacityCoeff(i, middle, baseLength)})` : `rgba(0, 0, 0, ${getOpacityCoeff(i, middle, baseLength)})`
// darken
}));
}
}
async function calcPos() {
await nextTick();
const barWidth = MazSlider2.value?.clientWidth;
typeof barWidth == "number" ? buttonPositions.value = tmpValues.value?.map(
(v) => __props.log ? barWidth / __props.max * (__props.min + (Math.log(v) - minLog.value) / scale.value) : barWidth / range.value * (v - __props.min)
) : console.warn("[maz-ui][MazSlider] ref component not found");
}
async function getCursorsValues() {
await nextTick();
const barWidth = MazSlider2.value?.clientWidth;
if (typeof barWidth == "number")
return __props.log ? buttonPositions.value?.map((pos) => {
const position = pos / (barWidth / __props.max), value = Math.exp((position - __props.min) * scale.value + minLog.value);
return roundToStep(Math.round(value));
}) : buttonPositions.value?.map(
(pos) => roundToStep(Math.round(pos / (barWidth / range.value)) + __props.min)
);
console.warn("[maz-ui][MazSlider] ref component not found");
}
function handleMousedown(_event, i) {
activeCursor.value === void 0 && (activeCursor.value = i, setBtnDividers(i));
}
async function handleMouseup() {
if (activeCursor.value === void 0)
return;
const values = await getCursorsValues();
values && emitValue(values), activeCursor.value = void 0;
}
async function handleMousemove(event) {
if (await nextTick(), activeCursor.value === void 0)
return;
const barWidth = MazSlider2.value?.clientWidth;
if (buttonPositions.value) {
const prevValue = buttonPositions.value[activeCursor.value - 1] || 0, nextValue = buttonPositions.value[activeCursor.value + 1] || barWidth;
if (!MazSlider2.value)
return console.error("[maz-ui](MazSlider/handleMousemove) MazSlider not available");
buttonPositions.value[activeCursor.value] = (() => {
const movement = getPos(event, MazSlider2.value).x;
return movement < prevValue ? prevValue : nextValue && movement > nextValue ? nextValue : movement;
})(), tmpValues.value = await getCursorsValues(), setBtnDividers(activeCursor.value);
}
}
return (_ctx, _cache) => (openBlock(), createElementBlock("div", {
style: normalizeStyle([wrapperStyle.value, { fontSize: __props.size }]),
class: normalizeClass(["m-slider m-reset-css", [`m-slider--${__props.color}`]]),
role: "button",
tabindex: "-1",
onMousemovePassive: handleMousemove,
onMouseupPassive: handleMouseup,
onMouseleavePassive: handleMouseup,
onTouchmovePassive: handleMousemove
}, [
createElementVNode("div", {
ref_key: "MazSlider",
ref: MazSlider2,
class: "m-slider__bar",
role: "slider",
"aria-valuenow": __props.modelValue?.toString(),
"aria-valuemin": __props.min,
"aria-valuemax": __props.max
}, [
(openBlock(!0), createElementBlock(Fragment, null, renderList(dividers.value, (div, i) => (openBlock(), createElementBlock("div", {
key: `divider-${i}`,
style: normalizeStyle([div]),
class: "m-slider__divider"
}, null, 4))), 128)),
(openBlock(!0), createElementBlock(Fragment, null, renderList(computedValue.value, (_btn, i) => (openBlock(), createElementBlock("button", {
key: `cursor-${i}`,
type: "button",
"data-label": getLabel(i),
class: normalizeClass(["m-slider__btn", {
"active-cursor": i === activeCursor.value && __props.cursorAnim
}]),
style: normalizeStyle([buttonStyles.value[i]]),
onMousedownPassive: ($event) => handleMousedown($event, i),
onTouchstartPassive: ($event) => handleMousedown($event, i),
onFocusPassive: ($event) => handleMousedown($event, i),
onBlurPassive: ($event) => blurCursor(i),
onTouchendPassive: ($event) => blurCursor(i),
onKeydownPassive: ($event) => cursorKeyDown($event, i)
}, [
createElementVNode("span", null, toDisplayString(tmpValues.value?.[i]), 1)
], 46, _hoisted_2))), 128))
], 8, _hoisted_1)
], 38));
}
}), MazSlider = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8cc966c7"]]);
export {
MazSlider as default
};