@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
536 lines (535 loc) • 21.9 kB
JavaScript
"use strict";
/*! Oruga v0.11.0 | MIT License | github.com/oruga-ui/oruga */
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const vue = require("vue");
const Tooltip_vue_vue_type_script_setup_true_lang = require("./Tooltip.vue_vue_type_script_setup_true_lang-BTZz3kR-.cjs");
const config = require("./config-eYBvpFOZ.cjs");
const fieldInjection = require("./fieldInjection-aGL6GpMR.cjs");
const defineClasses = require("./defineClasses-Cqhbv-UT.cjs");
const useParentProvider = require("./useParentProvider-CPNahRzD.cjs");
const helpers = require("./helpers.cjs");
const _hoisted_1 = ["tabindex", "aria-label", "aria-labelledby", "aria-valuenow", "aria-valuemin", "aria-valuemax", "aria-disabled", "onKeydown"];
const _hoisted_2 = { key: 0 };
const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
...{
isOruga: true,
name: "OSliderThumb",
configField: "slider",
inheritAttrs: false
},
__name: "SliderThumb",
props: {
sliderProps: {},
modelValue: {},
sliderSize: { type: Function },
thumbWrapperClasses: {},
thumbClasses: {}
},
emits: ["update:model-value", "change", "dragstart", "dragend"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const { parentField } = fieldInjection.injectField();
const isFocused = vue.ref(false);
const dragging = vue.ref(false);
const startX = vue.ref(0);
const startPosition = vue.ref(0);
const newPosition = vue.ref();
const oldValue = vue.ref(props.modelValue);
const tooltip = vue.computed(() => props.sliderProps.tooltip);
const tooltipAlways = vue.computed(() => props.sliderProps.tooltipAlways);
const disabled = vue.computed(() => props.sliderProps.disabled);
const max = vue.computed(() => props.sliderProps.max);
const min = vue.computed(() => props.sliderProps.min);
const step = vue.computed(() => props.sliderProps.step);
const indicator = vue.computed(() => props.sliderProps.indicator);
const ariaLabel = vue.computed(() => props.sliderProps.ariaLabel);
const precision = vue.computed(() => {
const precisions = [min.value, max.value, step.value].map((item) => {
const decimal = ("" + item).split(".")[1];
return decimal ? decimal.length : 0;
});
return Math.max(...precisions);
});
const computedTooltipVariant = vue.computed(
() => props.sliderProps.tooltipVariant ? props.sliderProps.tooltipVariant : props.sliderProps.variant
);
const currentPosition = vue.computed(
() => `${(props.modelValue - min.value) / (max.value - min.value) * 100}%`
);
const wrapperStyle = vue.computed(() => ({ left: currentPosition.value }));
const formattedValue = vue.computed(() => {
if (typeof props.sliderProps.formatter !== "undefined")
return props.sliderProps.formatter(props.modelValue);
if (props.sliderProps.format === "percent")
return new Intl.NumberFormat(props.sliderProps.locale, {
style: "percent"
}).format((props.modelValue - min.value) / (max.value - min.value));
return new Intl.NumberFormat(props.sliderProps.locale).format(
props.modelValue
);
});
function onFocus() {
isFocused.value = true;
}
function onBlur() {
isFocused.value = false;
}
function onButtonDown(event) {
if (disabled.value) return;
event.preventDefault();
onDragStart(event);
if (config.isClient) {
document.addEventListener("mousemove", onDragging);
document.addEventListener("touchmove", onDragging);
document.addEventListener("mouseup", onDragEnd);
document.addEventListener("touchend", onDragEnd);
document.addEventListener("contextmenu", onDragEnd);
}
}
function onLeftKeyDown() {
if (disabled.value || props.modelValue === min.value) return;
newPosition.value = parseFloat(currentPosition.value) - step.value / (max.value - min.value) * 100;
setPosition(newPosition.value);
emits("change");
}
function onRightKeyDown() {
if (disabled.value || props.modelValue === max.value) return;
newPosition.value = parseFloat(currentPosition.value) + step.value / (max.value - min.value) * 100;
setPosition(newPosition.value);
emits("change");
}
function onHomeKeyDown() {
if (disabled.value || props.modelValue === min.value) return;
newPosition.value = 0;
setPosition(newPosition.value);
emits("change");
}
function onEndKeyDown() {
if (disabled.value || props.modelValue === max.value) return;
newPosition.value = 100;
setPosition(newPosition.value);
emits("change");
}
function onDragStart(event) {
dragging.value = true;
emits("dragstart");
if (event.type === "touchstart") event.clientX = event.touches[0].clientX;
startX.value = event.clientX;
startPosition.value = parseFloat(currentPosition.value);
newPosition.value = startPosition.value;
}
function onDragging(event) {
if (dragging.value) {
if (event.type === "touchmove")
event.clientX = event.touches[0].clientX;
const diff = (event.clientX - startX.value) / props.sliderSize() * 100;
newPosition.value = startPosition.value + diff;
setPosition(newPosition.value);
}
}
function onDragEnd() {
dragging.value = false;
emits("dragend");
if (props.modelValue !== oldValue.value) emits("change");
setPosition(newPosition.value);
if (config.isClient) {
document.removeEventListener("mousemove", onDragging);
document.removeEventListener("touchmove", onDragging);
document.removeEventListener("mouseup", onDragEnd);
document.removeEventListener("touchend", onDragEnd);
document.removeEventListener("contextmenu", onDragEnd);
}
}
function setPosition(percent) {
if (percent === void 0 || isNaN(percent)) return;
if (percent < 0) percent = 0;
else if (percent > 100) percent = 100;
const stepLength = 100 / ((max.value - min.value) / step.value);
const steps = Math.round(percent / stepLength);
let value = steps * stepLength / 100 * (max.value - min.value) + min.value;
value = parseFloat(value.toFixed(precision.value));
emits("update:model-value", value);
if (!dragging.value && value !== oldValue.value) oldValue.value = value;
}
__expose({ setPosition });
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
"data-oruga": "slider-thumb",
class: vue.normalizeClass(_ctx.thumbWrapperClasses),
style: vue.normalizeStyle(wrapperStyle.value)
}, [
vue.createVNode(Tooltip_vue_vue_type_script_setup_true_lang._sfc_main, {
label: formattedValue.value,
variant: computedTooltipVariant.value,
disabled: disabled.value || !tooltip.value,
always: tooltipAlways.value || dragging.value || isFocused.value
}, {
default: vue.withCtx(() => {
var _a;
return [
vue.createElementVNode("div", vue.mergeProps(_ctx.$attrs, {
class: _ctx.thumbClasses,
tabindex: disabled.value ? void 0 : 0,
role: "slider",
"aria-label": ariaLabel.value,
"aria-labelledby": (_a = vue.unref(parentField)) == null ? void 0 : _a.labelId,
"aria-valuenow": _ctx.modelValue,
"aria-valuemin": min.value,
"aria-valuemax": max.value,
"aria-disabled": disabled.value,
"aria-orientation": "horizontal",
onMousedown: onButtonDown,
onTouchstartPassive: onButtonDown,
onFocus,
onBlur,
onKeydown: [
vue.withKeys(vue.withModifiers(onLeftKeyDown, ["prevent"]), ["left"]),
vue.withKeys(vue.withModifiers(onRightKeyDown, ["prevent"]), ["right"]),
vue.withKeys(vue.withModifiers(onLeftKeyDown, ["prevent"]), ["down"]),
vue.withKeys(vue.withModifiers(onRightKeyDown, ["prevent"]), ["up"]),
vue.withKeys(vue.withModifiers(onHomeKeyDown, ["prevent"]), ["home"]),
vue.withKeys(vue.withModifiers(onEndKeyDown, ["prevent"]), ["end"])
]
}), [
indicator.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_2, vue.toDisplayString(formattedValue.value), 1)) : vue.createCommentVNode("", true)
], 16, _hoisted_1)
];
}),
_: 1
}, 8, ["label", "variant", "disabled", "always"])
], 6);
};
}
});
const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
...{
isOruga: true,
name: "OSliderTick",
configField: "slider"
},
__name: "SliderTick",
props: {
/** Override existing theme classes completely */
override: { type: Boolean, default: void 0 },
/** Value of single tick */
value: { type: Number, required: true },
/** Tick label */
label: { type: [String, Number], default: void 0 },
tickClass: {
type: [String, Function, Array],
default: void 0
},
/** Class when slider tick is hidden */
tickHiddenClass: {
type: [String, Function, Array],
default: void 0
},
/** Class of tick label */
tickLabelClass: {
type: [String, Function, Array],
default: void 0
}
},
setup(__props) {
const props = __props;
const { parent } = useParentProvider.useProviderChild({ register: false });
const position = vue.computed(() => {
const pos = (props.value - parent.value.min) / (parent.value.max - parent.value.min) * 100;
return pos >= 0 && pos <= 100 ? pos : 0;
});
const hidden = vue.computed(
() => props.value === parent.value.min || props.value === parent.value.max
);
const tickStyle = vue.computed(() => ({ left: position.value + "%" }));
const rootClasses = defineClasses.defineClasses(
["tickClass", "o-slider__tick"],
["tickHiddenClass", "o-slider__tick--hidden", null, hidden]
);
const tickLabelClasses = defineClasses.defineClasses([
"tickLabelClass",
"o-slider__tick-label"
]);
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
"data-oruga": "slider-tick",
class: vue.normalizeClass(vue.unref(rootClasses)),
style: vue.normalizeStyle(tickStyle.value)
}, [
_ctx.$slots.default || __props.label ? (vue.openBlock(), vue.createElementBlock("span", {
key: 0,
class: vue.normalizeClass(vue.unref(tickLabelClasses))
}, [
vue.renderSlot(_ctx.$slots, "default", {}, () => [
vue.createTextVNode(vue.toDisplayString(__props.label), 1)
])
], 2)) : vue.createCommentVNode("", true)
], 6);
};
}
});
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
...{
isOruga: true,
name: "OSlider",
configField: "slider"
},
__name: "Slider",
props: {
override: { type: Boolean, default: void 0 },
modelValue: { default: void 0 },
range: {},
min: { default: 0 },
max: { default: 100 },
step: { default: 1 },
variant: { default: () => config.getDefault("slider.variant") },
size: { default: () => config.getDefault("slider.size") },
ticks: { type: Boolean, default: false },
tooltip: { type: Boolean, default: () => config.getDefault("slider.tooltip", true) },
tooltipVariant: { default: () => config.getDefault("slider.tooltipVariant") },
tooltipAlways: { type: Boolean, default: false },
rounded: { type: Boolean, default: () => config.getDefault("slider.rounded", false) },
disabled: { type: Boolean, default: false },
lazy: { type: Boolean, default: false },
formatter: { type: Function, default: void 0 },
biggerSliderFocus: { type: Boolean, default: false },
indicator: { type: Boolean, default: false },
format: { default: () => config.getDefault("slider.format", "raw") },
locale: { default: () => config.getDefault("locale") },
ariaLabel: { default: () => config.getDefault("slider.ariaLabel") },
rootClass: {},
sizeClass: {},
disabledClass: {},
trackClass: {},
fillClass: {},
variantClass: {},
thumbWrapperClass: {},
thumbWrapperDraggingClass: {},
thumbClass: {},
thumbRoundedClass: {},
thumbDraggingClass: {},
tickClass: {},
tickHiddenClass: {},
tickLabelClass: {}
},
emits: ["update:model-value", "change", "dragging", "dragstart", "dragend"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const sliderRef = vue.useTemplateRef("sliderElement");
const thumbStartRef = vue.useTemplateRef("thumbStartComponent");
const thumbEndRef = vue.useTemplateRef("thumbEndComponent");
const provideData = vue.computed(() => ({
max: props.max,
min: props.min
}));
useParentProvider.useProviderParent({ data: provideData });
const valueStart = vue.ref(0);
const valueEnd = vue.ref(0);
const dragging = vue.ref(false);
const isThumbReversed = vue.ref();
const isTrackClickDisabled = vue.ref();
const minValue = vue.computed(
() => Math.min(valueStart.value || props.min, valueEnd.value || props.max)
);
const maxValue = vue.computed(
() => Math.max(valueStart.value || props.min, valueEnd.value || props.max)
);
const isRange = vue.computed(() => helpers.isTrueish(props.range));
const vmodel = vue.computed(
() => isRange.value ? [minValue.value, maxValue.value] : valueStart.value || 0
);
vue.watch([valueStart, valueEnd], () => {
if (isRange.value)
isThumbReversed.value = valueStart.value && valueEnd.value ? valueStart.value > valueEnd.value : false;
if (!props.lazy || !dragging.value)
emits("update:model-value", vmodel.value);
if (dragging.value) emits("dragging", vmodel.value);
});
vue.watch(
[() => props.min, () => props.max, () => props.modelValue],
() => setValues(props.modelValue),
{ immediate: true }
// initialise valueStart and valueEnd
);
function setValues(newValue) {
if (props.min > props.max) return;
if (Array.isArray(newValue)) {
const smallValue = typeof newValue[0] !== "number" || isNaN(newValue[0]) ? props.min : Math.min(Math.max(props.min, newValue[0]), props.max);
const largeValue = typeof newValue[1] !== "number" || isNaN(newValue[1]) ? props.max : Math.max(Math.min(props.max, newValue[1]), props.min);
valueStart.value = isThumbReversed.value ? largeValue : smallValue;
valueEnd.value = isThumbReversed.value ? smallValue : largeValue;
} else if (newValue !== void 0) {
valueStart.value = isNaN(newValue) ? props.min : Math.min(props.max, Math.max(props.min, newValue));
valueEnd.value = 0;
} else {
valueStart.value = props.min;
valueEnd.value = props.min;
}
}
const tickValues = vue.computed(() => {
if (!props.ticks || props.min > props.max || props.step === 0) return [];
const result = [];
for (let i = props.min + props.step; i < props.max; i = i + props.step) {
result.push(i);
}
return result;
});
const barSize = vue.computed(
() => isRange.value ? `${100 * (maxValue.value - minValue.value) / (props.max - props.min)}%` : `${100 * (valueStart.value - props.min) / (props.max - props.min)}%`
);
const barStart = vue.computed(
() => isRange.value ? `${100 * (minValue.value - props.min) / (props.max - props.min)}%` : "0%"
);
const barStyle = vue.computed(() => ({
width: barSize.value,
left: barStart.value
}));
function getSliderSize() {
var _a;
return ((_a = sliderRef.value) == null ? void 0 : _a.getBoundingClientRect().width) || 0;
}
function onSliderClick(event) {
if (props.disabled || isTrackClickDisabled.value) return;
if (!sliderRef.value || !thumbStartRef.value || isRange.value && !thumbEndRef.value)
return;
const sliderOffsetLeft = sliderRef.value.getBoundingClientRect().left;
const percent = (event.clientX - sliderOffsetLeft) / getSliderSize() * 100;
const targetValue = props.min + percent * (props.max - props.min) / 100;
const diffFirst = Math.abs(targetValue - valueStart.value);
if (!isRange.value) {
if (diffFirst < props.step / 2) return;
thumbStartRef.value.setPosition(percent);
} else {
const diffSecond = Math.abs(targetValue - valueEnd.value);
if (diffFirst <= diffSecond) {
if (diffFirst < props.step / 2) return;
thumbStartRef.value.setPosition(percent);
} else {
if (diffSecond < props.step / 2) return;
if (isRange.value && thumbEndRef.value)
thumbEndRef.value.setPosition(percent);
}
}
emits("change", vmodel.value);
}
function onDragStart() {
dragging.value = true;
emits("dragstart");
}
function onDragEnd() {
isTrackClickDisabled.value = true;
setTimeout(() => isTrackClickDisabled.value = false);
dragging.value = false;
emits("dragend");
if (props.lazy) emits("update:model-value", vmodel.value);
}
const rootClasses = defineClasses.defineClasses(
["rootClass", "o-slider"],
[
"sizeClass",
"o-slider--",
vue.computed(() => props.size),
vue.computed(() => !!props.size)
],
[
"disabledClass",
"o-slider--disabled",
null,
vue.computed(() => props.disabled)
]
);
const trackClasses = defineClasses.defineClasses(["trackClass", "o-slider__track"]);
const fillClasses = defineClasses.defineClasses(
["fillClass", "o-slider__fill"],
[
"variantClass",
"o-slider__fill--",
vue.computed(() => props.variant),
vue.computed(() => !!props.variant)
]
);
const thumbWrapperClasses = defineClasses.defineClasses(
["thumbWrapperClass", "o-slider__thumb-wrapper"],
[
"thumbWrapperDraggingClass",
"o-slider__thumb-wrapper--dragging",
null,
dragging
]
);
const thumbClasses = defineClasses.defineClasses(
["thumbClass", "o-slider__thumb"],
["thumbDraggingClass", "o-slider__thumb--dragging", null, dragging],
[
"thumbRoundedClass",
"o-slider__thumb--rounded",
null,
vue.computed(() => props.rounded)
]
);
__expose({ value: vmodel });
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", {
"data-oruga": "slider",
class: vue.normalizeClass(vue.unref(rootClasses)),
onClick: onSliderClick
}, [
vue.createElementVNode("div", {
ref: "sliderElement",
class: vue.normalizeClass(vue.unref(trackClasses))
}, [
vue.createElementVNode("div", {
class: vue.normalizeClass(vue.unref(fillClasses)),
style: vue.normalizeStyle(barStyle.value)
}, null, 6),
_ctx.ticks ? (vue.openBlock(true), vue.createElementBlock(vue.Fragment, { key: 0 }, vue.renderList(tickValues.value, (val, key) => {
return vue.openBlock(), vue.createBlock(_sfc_main$1, {
key,
value: val,
"tick-class": _ctx.tickClass,
"tick-hidden-class": _ctx.tickHiddenClass,
"tick-label-class": _ctx.tickLabelClass
}, null, 8, ["value", "tick-class", "tick-hidden-class", "tick-label-class"]);
}), 128)) : vue.createCommentVNode("", true),
vue.renderSlot(_ctx.$slots, "default"),
vue.createVNode(_sfc_main$2, {
ref: "thumbStartComponent",
modelValue: valueStart.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => valueStart.value = $event),
"slider-props": props,
"slider-size": getSliderSize,
"thumb-classes": vue.unref(thumbClasses),
"thumb-wrapper-classes": vue.unref(thumbWrapperClasses),
onChange: _cache[1] || (_cache[1] = ($event) => emits("change", vmodel.value)),
onDragstart: onDragStart,
onDragend: onDragEnd
}, null, 8, ["modelValue", "thumb-classes", "thumb-wrapper-classes"]),
isRange.value ? (vue.openBlock(), vue.createBlock(_sfc_main$2, {
key: 1,
ref: "thumbEndComponent",
modelValue: valueEnd.value,
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => valueEnd.value = $event),
"slider-props": props,
"slider-size": getSliderSize,
"thumb-classes": vue.unref(thumbClasses),
"thumb-wrapper-classes": vue.unref(thumbWrapperClasses),
onChange: _cache[3] || (_cache[3] = ($event) => emits("change", vmodel.value)),
onDragstart: onDragStart,
onDragend: onDragEnd
}, null, 8, ["modelValue", "thumb-classes", "thumb-wrapper-classes"])) : vue.createCommentVNode("", true)
], 2)
], 2);
};
}
});
const index = {
install(app) {
config.registerComponent(app, _sfc_main);
config.registerComponent(app, _sfc_main$1);
}
};
exports.OSlider = _sfc_main;
exports.OSliderTick = _sfc_main$1;
exports.default = index;
//# sourceMappingURL=slider.cjs.map