buefy
Version:
Lightweight UI components for Vue.js (v3) based on Bulma
700 lines (688 loc) • 22.1 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
var Tooltip = require('./Tooltip-Cgighv0j.js');
var config = require('./config-DR826Ki2.js');
var CompatFallthroughMixin = require('./CompatFallthroughMixin-hhK0Gkhr.js');
var _pluginVue_exportHelper = require('./_plugin-vue_export-helper-Die8u8yB.js');
var helpers = require('./helpers.js');
var plugins = require('./plugins-DbyYGVpp.js');
const DISPLAY_FORMATS = ["raw", "percent"];
var _sfc_main$2 = vue.defineComponent({
name: "BSliderThumb",
components: {
BTooltip: Tooltip.Tooltip
},
mixins: [CompatFallthroughMixin.CompatFallthroughMixin],
props: {
modelValue: {
type: Number,
default: 0
},
type: {
type: String,
default: ""
},
tooltip: {
type: Boolean,
default: true
},
indicator: {
type: Boolean,
default: false
},
customFormatter: Function,
format: {
type: String,
default: "raw",
validator: (value) => {
return DISPLAY_FORMATS.indexOf(value) >= 0;
}
},
locale: {
type: [String, Array],
default: () => {
return config.config.defaultLocale;
}
},
tooltipAlways: {
type: Boolean,
default: false
}
},
emits: {
dragend: () => true,
dragstart: () => true,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
"update:modelValue": (_value) => true
},
data() {
return {
isFocused: false,
dragging: false,
startX: 0,
startPosition: 0,
newPosition: null,
oldValue: this.modelValue
};
},
computed: {
parent() {
return this.$parent;
},
disabled() {
return this.parent.disabled;
},
max() {
return this.parent.max;
},
min() {
return this.parent.min;
},
step() {
return this.parent.step;
},
precision() {
return this.parent.precision;
},
currentPosition() {
return `${(this.modelValue - this.min) / (this.max - this.min) * 100}%`;
},
wrapperStyle() {
return { left: this.currentPosition };
},
formattedValue() {
if (typeof this.customFormatter !== "undefined") {
return this.customFormatter(this.modelValue);
}
if (this.format === "percent") {
return new Intl.NumberFormat(
this.locale,
{
style: "percent"
}
).format((this.modelValue - this.min) / (this.max - this.min));
}
return new Intl.NumberFormat(this.locale).format(this.modelValue);
}
},
methods: {
onFocus() {
this.isFocused = true;
},
onBlur() {
this.isFocused = false;
},
onButtonDown(event) {
if (this.disabled) return;
event.preventDefault();
this.onDragStart(event);
if (typeof window !== "undefined") {
document.addEventListener("mousemove", this.onDragging);
document.addEventListener("touchmove", this.onDragging);
document.addEventListener("mouseup", this.onDragEnd);
document.addEventListener("touchend", this.onDragEnd);
document.addEventListener("contextmenu", this.onDragEnd);
}
},
onLeftKeyDown() {
if (this.disabled || this.modelValue === this.min) return;
this.newPosition = parseFloat(this.currentPosition) - this.step / (this.max - this.min) * 100;
this.setPosition(this.newPosition);
this.parent.emitValue("change");
},
onRightKeyDown() {
if (this.disabled || this.modelValue === this.max) return;
this.newPosition = parseFloat(this.currentPosition) + this.step / (this.max - this.min) * 100;
this.setPosition(this.newPosition);
this.parent.emitValue("change");
},
onHomeKeyDown() {
if (this.disabled || this.modelValue === this.min) return;
this.newPosition = 0;
this.setPosition(this.newPosition);
this.parent.emitValue("change");
},
onEndKeyDown() {
if (this.disabled || this.modelValue === this.max) return;
this.newPosition = 100;
this.setPosition(this.newPosition);
this.parent.emitValue("change");
},
onDragStart(event) {
this.dragging = true;
this.$emit("dragstart");
this.startX = event.type === "touchstart" ? event.touches[0].clientX : event.clientX;
this.startPosition = parseFloat(this.currentPosition);
this.newPosition = this.startPosition;
},
onDragging(event) {
if (this.dragging) {
const clientX = event.type === "touchmove" ? event.touches[0].clientX : event.clientX;
const diff = (clientX - this.startX) / this.parent.sliderSize() * 100;
this.newPosition = this.startPosition + diff;
this.setPosition(this.newPosition);
}
},
onDragEnd() {
this.dragging = false;
this.$emit("dragend");
if (this.modelValue !== this.oldValue) {
this.parent.emitValue("change");
}
this.setPosition(this.newPosition);
if (typeof window !== "undefined") {
document.removeEventListener("mousemove", this.onDragging);
document.removeEventListener("touchmove", this.onDragging);
document.removeEventListener("mouseup", this.onDragEnd);
document.removeEventListener("touchend", this.onDragEnd);
document.removeEventListener("contextmenu", this.onDragEnd);
}
},
setPosition(percent) {
if (percent === null || isNaN(percent)) return;
if (percent < 0) {
percent = 0;
} else if (percent > 100) {
percent = 100;
}
const stepLength = 100 / ((this.max - this.min) / this.step);
const steps = Math.round(percent / stepLength);
let value = steps * stepLength / 100 * (this.max - this.min) + this.min;
value = parseFloat(value.toFixed(this.precision));
this.$emit("update:modelValue", value);
if (!this.dragging && value !== this.oldValue) {
this.oldValue = value;
}
}
},
beforeUnmount() {
document.removeEventListener("mousemove", this.onDragging);
document.removeEventListener("touchmove", this.onDragging);
document.removeEventListener("mouseup", this.onDragEnd);
document.removeEventListener("touchend", this.onDragEnd);
document.removeEventListener("contextmenu", this.onDragEnd);
}
});
const _hoisted_1$2 = ["tabindex"];
const _hoisted_2 = { key: 0 };
function _sfc_render$2(_ctx, _cache, $props, $setup, $data, $options) {
const _component_b_tooltip = vue.resolveComponent("b-tooltip");
return vue.openBlock(), vue.createElementBlock(
"div",
vue.mergeProps({
class: ["b-slider-thumb-wrapper", { "is-dragging": _ctx.dragging, "has-indicator": _ctx.indicator }],
style: _ctx.wrapperStyle
}, _ctx.rootAttrs),
[
vue.createVNode(_component_b_tooltip, {
label: _ctx.formattedValue,
type: _ctx.type,
always: _ctx.dragging || _ctx.isFocused || _ctx.tooltipAlways,
active: !_ctx.disabled && _ctx.tooltip
}, {
default: vue.withCtx(() => [
vue.createElementVNode("div", vue.mergeProps({
class: "b-slider-thumb",
tabindex: _ctx.disabled ? void 0 : 0
}, _ctx.fallthroughAttrs, {
onMousedown: _cache[0] || (_cache[0] = (...args) => _ctx.onButtonDown && _ctx.onButtonDown(...args)),
onTouchstart: _cache[1] || (_cache[1] = (...args) => _ctx.onButtonDown && _ctx.onButtonDown(...args)),
onFocus: _cache[2] || (_cache[2] = (...args) => _ctx.onFocus && _ctx.onFocus(...args)),
onBlur: _cache[3] || (_cache[3] = (...args) => _ctx.onBlur && _ctx.onBlur(...args)),
onKeydown: [
_cache[4] || (_cache[4] = vue.withKeys(vue.withModifiers((...args) => _ctx.onLeftKeyDown && _ctx.onLeftKeyDown(...args), ["prevent"]), ["left"])),
_cache[5] || (_cache[5] = vue.withKeys(vue.withModifiers((...args) => _ctx.onRightKeyDown && _ctx.onRightKeyDown(...args), ["prevent"]), ["right"])),
_cache[6] || (_cache[6] = vue.withKeys(vue.withModifiers((...args) => _ctx.onLeftKeyDown && _ctx.onLeftKeyDown(...args), ["prevent"]), ["down"])),
_cache[7] || (_cache[7] = vue.withKeys(vue.withModifiers((...args) => _ctx.onRightKeyDown && _ctx.onRightKeyDown(...args), ["prevent"]), ["up"])),
_cache[8] || (_cache[8] = vue.withKeys(vue.withModifiers((...args) => _ctx.onHomeKeyDown && _ctx.onHomeKeyDown(...args), ["prevent"]), ["home"])),
_cache[9] || (_cache[9] = vue.withKeys(vue.withModifiers((...args) => _ctx.onEndKeyDown && _ctx.onEndKeyDown(...args), ["prevent"]), ["end"]))
]
}), [
_ctx.indicator ? (vue.openBlock(), vue.createElementBlock(
"span",
_hoisted_2,
vue.toDisplayString(_ctx.formattedValue),
1
/* TEXT */
)) : vue.createCommentVNode("v-if", true)
], 16, _hoisted_1$2)
]),
_: 1
/* STABLE */
}, 8, ["label", "type", "always", "active"])
],
16
/* FULL_PROPS */
);
}
var BSliderThumb = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$2, [["render", _sfc_render$2]]);
var _sfc_main$1 = vue.defineComponent({
name: "BSliderTick",
props: {
value: {
type: Number,
default: 0
}
},
computed: {
parent() {
return this.$parent;
},
position() {
const pos = (this.value - this.parent.min) / (this.parent.max - this.parent.min) * 100;
return pos >= 0 && pos <= 100 ? pos : 0;
},
hidden() {
return this.value === this.parent.min || this.value === this.parent.max;
}
},
methods: {
getTickStyle(position) {
return { left: position + "%" };
}
},
created() {
if (!this.parent.$data._isSlider) {
throw new Error("You should wrap bSliderTick on a bSlider");
}
}
});
const _hoisted_1$1 = {
key: 0,
class: "b-slider-tick-label"
};
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
return vue.openBlock(), vue.createElementBlock(
"div",
{
class: vue.normalizeClass(["b-slider-tick", { "is-tick-hidden": _ctx.hidden }]),
style: vue.normalizeStyle(_ctx.getTickStyle(_ctx.position))
},
[
_ctx.$slots.default ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_1$1, [
vue.renderSlot(_ctx.$slots, "default")
])) : vue.createCommentVNode("v-if", true)
],
6
/* CLASS, STYLE */
);
}
var SliderTick = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main$1, [["render", _sfc_render$1]]);
var _sfc_main = vue.defineComponent({
name: "BSlider",
components: {
BSliderThumb,
BSliderTick: SliderTick
},
props: {
modelValue: {
type: [Number, Array],
default: 0
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
},
type: {
type: String,
default: "is-primary"
},
size: String,
ticks: {
type: Boolean,
default: false
},
tooltip: {
type: Boolean,
default: true
},
tooltipType: String,
rounded: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
lazy: {
type: Boolean,
default: false
},
customFormatter: Function,
ariaLabel: [String, Array],
biggerSliderFocus: {
type: Boolean,
default: false
},
indicator: {
type: Boolean,
default: false
},
format: {
type: String,
default: "raw",
validator: (value) => {
return DISPLAY_FORMATS.indexOf(value) >= 0;
}
},
locale: {
type: [String, Array],
default: () => {
return config.config.defaultLocale;
}
},
tooltipAlways: {
type: Boolean,
default: false
}
},
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
change: (_value) => true,
dragend: () => true,
dragging: (_value) => true,
dragstart: () => true,
"update:modelValue": (_value) => true
/* eslint-enable @typescript-eslint/no-unused-vars */
},
data() {
return {
value1: void 0,
value2: void 0,
// internal is used to update value1 and value2 with a single shot.
// internal is also used to stop unnecessary propagation of update.
internal: {
value1: void 0,
value2: void 0
},
dragging: false,
isRange: false,
isThumbReversed: false,
isTrackClickDisabled: false,
_isSlider: true,
// Used by Thumb and Tick
timeOutID: void 0
};
},
computed: {
newTooltipType() {
return this.tooltipType ? this.tooltipType : this.type;
},
tickValues() {
if (!this.ticks || this.min > this.max || this.step === 0) return [];
const result = [];
for (let i = this.min + this.step; i < this.max; i = i + this.step) {
result.push(i);
}
return result;
},
minValue() {
return Math.min(this.value1, this.value2);
},
maxValue() {
return Math.max(this.value1, this.value2);
},
barSize() {
return this.isRange ? `${100 * (this.maxValue - this.minValue) / (this.max - this.min)}%` : `${100 * (this.value1 - this.min) / (this.max - this.min)}%`;
},
barStart() {
return this.isRange ? `${100 * (this.minValue - this.min) / (this.max - this.min)}%` : "0%";
},
precision() {
const precisions = [this.min, this.max, this.step].map((item) => {
const decimal = ("" + item).split(".")[1];
return decimal ? decimal.length : 0;
});
return Math.max(...precisions);
},
barStyle() {
return {
width: this.barSize,
left: this.barStart
};
},
rootClasses() {
return {
"is-rounded": this.rounded,
"is-dragging": this.dragging,
"is-disabled": this.disabled,
"slider-focus": this.biggerSliderFocus
};
}
},
watch: {
/*
* When v-model is changed set the new active step.
*/
modelValue(value) {
this.setValues(value);
},
internal({ value1, value2 }) {
this.value1 = value1;
this.value2 = value2;
},
value1(newValue) {
if (this.internal.value1 !== newValue) {
this.onInternalValueUpdate();
}
},
value2(newValue) {
if (this.internal.value2 !== newValue) {
this.onInternalValueUpdate();
}
},
min() {
this.setValues(this.modelValue);
},
max() {
this.setValues(this.modelValue);
}
},
methods: {
setValues(newValue) {
if (this.min > this.max) {
return;
}
if (Array.isArray(newValue)) {
this.isRange = true;
const smallValue = typeof newValue[0] !== "number" || isNaN(newValue[0]) ? this.min : helpers.bound(newValue[0], this.min, this.max);
const largeValue = typeof newValue[1] !== "number" || isNaN(newValue[1]) ? this.max : helpers.bound(newValue[1], this.min, this.max);
this.internal = {
value1: this.isThumbReversed ? largeValue : smallValue,
value2: this.isThumbReversed ? smallValue : largeValue
};
} else {
this.isRange = false;
this.internal = {
value1: isNaN(newValue) ? this.min : helpers.bound(newValue, this.min, this.max),
value2: void 0
};
}
},
onInternalValueUpdate() {
if (this.isRange) {
this.isThumbReversed = this.value1 > this.value2;
}
if (!this.lazy || !this.dragging) {
this.emitValue("update:modelValue");
}
if (this.dragging) {
this.emitValue("dragging");
}
},
sliderSize() {
return this.$refs.slider.getBoundingClientRect().width;
},
onSliderClick(event) {
if (this.disabled || this.isTrackClickDisabled) return;
const sliderOffsetLeft = this.$refs.slider.getBoundingClientRect().left;
const percent = (event.clientX - sliderOffsetLeft) / this.sliderSize() * 100;
const targetValue = this.min + percent * (this.max - this.min) / 100;
const diffFirst = Math.abs(targetValue - this.value1);
if (!this.isRange) {
if (diffFirst < this.step / 2) return;
this.$refs.button1.setPosition(percent);
} else {
const diffSecond = Math.abs(targetValue - this.value2);
if (diffFirst <= diffSecond) {
if (diffFirst < this.step / 2) return;
this.$refs.button1.setPosition(percent);
} else {
if (diffSecond < this.step / 2) return;
this.$refs.button2.setPosition(percent);
}
}
this.emitValue("change");
},
onDragStart() {
this.dragging = true;
this.$emit("dragstart");
},
onDragEnd() {
this.isTrackClickDisabled = true;
this.timeOutID = setTimeout(() => {
this.isTrackClickDisabled = false;
}, 0);
this.dragging = false;
this.$emit("dragend");
if (this.lazy) {
this.emitValue("update:modelValue");
}
},
emitValue(type) {
const emittedValue = this.isRange ? [this.minValue, this.maxValue] : this.value1;
switch (type) {
case "change":
this.$emit(type, emittedValue);
break;
case "dragging":
this.$emit(type, emittedValue);
break;
case "update:modelValue":
this.$emit(type, emittedValue);
break;
}
}
},
created() {
this.isThumbReversed = false;
this.isTrackClickDisabled = false;
this.setValues(this.modelValue);
},
beforeUnmount() {
clearTimeout(this.timeOutID);
}
});
const _hoisted_1 = {
class: "b-slider-track",
ref: "slider"
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_b_slider_tick = vue.resolveComponent("b-slider-tick");
const _component_b_slider_thumb = vue.resolveComponent("b-slider-thumb");
return vue.openBlock(), vue.createElementBlock(
"div",
{
class: vue.normalizeClass(["b-slider", [_ctx.size, _ctx.type, _ctx.rootClasses]]),
onClick: _cache[2] || (_cache[2] = (...args) => _ctx.onSliderClick && _ctx.onSliderClick(...args))
},
[
vue.createElementVNode(
"div",
_hoisted_1,
[
vue.createElementVNode(
"div",
{
class: "b-slider-fill",
style: vue.normalizeStyle(_ctx.barStyle)
},
null,
4
/* STYLE */
),
_ctx.ticks ? (vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
{ key: 0 },
vue.renderList(_ctx.tickValues, (val, key) => {
return vue.openBlock(), vue.createBlock(_component_b_slider_tick, {
key,
value: val
}, null, 8, ["value"]);
}),
128
/* KEYED_FRAGMENT */
)) : vue.createCommentVNode("v-if", true),
vue.renderSlot(_ctx.$slots, "default"),
vue.createVNode(_component_b_slider_thumb, {
"tooltip-always": _ctx.tooltipAlways,
modelValue: _ctx.value1,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.value1 = $event),
type: _ctx.newTooltipType,
tooltip: _ctx.tooltip,
"custom-formatter": _ctx.customFormatter,
indicator: _ctx.indicator,
format: _ctx.format,
locale: _ctx.locale,
ref: "button1",
role: "slider",
"aria-valuenow": _ctx.value1,
"aria-valuemin": _ctx.min,
"aria-valuemax": _ctx.max,
"aria-orientation": "horizontal",
"aria-label": Array.isArray(_ctx.ariaLabel) ? _ctx.ariaLabel[0] : _ctx.ariaLabel,
"aria-disabled": _ctx.disabled || void 0,
onDragstart: _ctx.onDragStart,
onDragend: _ctx.onDragEnd
}, null, 8, ["tooltip-always", "modelValue", "type", "tooltip", "custom-formatter", "indicator", "format", "locale", "aria-valuenow", "aria-valuemin", "aria-valuemax", "aria-label", "aria-disabled", "onDragstart", "onDragend"]),
_ctx.isRange ? (vue.openBlock(), vue.createBlock(_component_b_slider_thumb, {
key: 1,
"tooltip-always": _ctx.tooltipAlways,
modelValue: _ctx.value2,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => _ctx.value2 = $event),
type: _ctx.newTooltipType,
tooltip: _ctx.tooltip,
"custom-formatter": _ctx.customFormatter,
indicator: _ctx.indicator,
format: _ctx.format,
locale: _ctx.locale,
ref: "button2",
role: "slider",
"aria-valuenow": _ctx.value2,
"aria-valuemin": _ctx.min,
"aria-valuemax": _ctx.max,
"aria-orientation": "horizontal",
"aria-label": Array.isArray(_ctx.ariaLabel) ? _ctx.ariaLabel[1] : "",
"aria-disabled": _ctx.disabled || void 0,
onDragstart: _ctx.onDragStart,
onDragend: _ctx.onDragEnd
}, null, 8, ["tooltip-always", "modelValue", "type", "tooltip", "custom-formatter", "indicator", "format", "locale", "aria-valuenow", "aria-valuemin", "aria-valuemax", "aria-label", "aria-disabled", "onDragstart", "onDragend"])) : vue.createCommentVNode("v-if", true)
],
512
/* NEED_PATCH */
)
],
2
/* CLASS */
);
}
var Slider = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["render", _sfc_render]]);
const Plugin = {
install(Vue) {
plugins.registerComponent(Vue, Slider);
plugins.registerComponent(Vue, SliderTick);
}
};
exports.BSlider = Slider;
exports.BSliderTick = SliderTick;
exports.default = Plugin;