buefy
Version:
Lightweight UI components for Vue.js (v3) based on Bulma
426 lines (419 loc) • 13.3 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var vue = require('vue');
var helpers = require('./helpers.js');
var Tag = require('./Tag-BprnwJJ1.js');
var Autocomplete = require('./Autocomplete-DEUs3z7g.js');
var config = require('./config-DR826Ki2.js');
var CompatFallthroughMixin = require('./CompatFallthroughMixin-hhK0Gkhr.js');
var FormElementMixin = require('./FormElementMixin-DavX4iOv.js');
var _pluginVue_exportHelper = require('./_plugin-vue_export-helper-Die8u8yB.js');
var plugins = require('./plugins-DbyYGVpp.js');
require('./Icon-lsDKE2wQ.js');
require('./Input-BcloGeZ3.js');
var _sfc_main = vue.defineComponent({
name: "BTaginput",
components: {
BAutocomplete: Autocomplete.BAutocomplete,
BTag: Tag.BTag
},
mixins: [CompatFallthroughMixin.CompatFallthroughMixin, FormElementMixin.FormElementMixin],
props: {
modelValue: {
type: Array,
default: () => []
},
data: {
type: Array,
default: () => []
},
type: String,
closeType: String,
attached: {
type: Boolean,
default: false
},
maxtags: Number,
hasCounter: {
type: Boolean,
default: () => config.config.defaultTaginputHasCounter
},
field: {
type: String,
default: "value"
},
autocomplete: Boolean,
groupField: String,
groupOptions: String,
nativeAutocomplete: String,
openOnFocus: Boolean,
keepOpen: {
type: Boolean,
default: true
},
keepFirst: Boolean,
disabled: Boolean,
ellipsis: Boolean,
closable: {
type: Boolean,
default: true
},
ariaCloseLabel: String,
confirmKeys: {
type: Array,
default: () => [",", "Tab", "Enter"]
},
removeOnKeys: {
type: Array,
default: () => ["Backspace"]
},
allowNew: Boolean,
onPasteSeparators: {
type: Array,
default: () => [","]
},
beforeAdding: {
type: Function,
default: () => true
},
allowDuplicates: {
type: Boolean,
default: false
},
checkInfiniteScroll: {
type: Boolean,
default: false
},
createTag: {
type: Function,
default: (tag) => tag
},
appendToBody: Boolean
},
emits: {
/* eslint-disable @typescript-eslint/no-unused-vars */
add: (tag) => true,
"infinite-scroll": () => true,
remove: (tag) => true,
typing: (value) => true,
"update:modelValue": (tags) => true
/* eslint-enable @typescript-eslint/no-unused-vars */
},
data() {
return {
tags: Array.isArray(this.modelValue) ? this.modelValue.slice(0) : this.modelValue || [],
newTag: "",
isComposing: false,
_elementRef: "autocomplete",
_isTaginput: true,
requestID: null
};
},
computed: {
rootClasses() {
return {
"is-expanded": this.expanded
};
},
containerClasses() {
return {
"is-focused": this.isFocused,
"is-focusable": this.hasInput
};
},
valueLength() {
return this.newTag.trim().length;
},
hasDefaultSlot() {
return !!this.$slots.default;
},
hasEmptySlot() {
return !!this.$slots.empty;
},
hasHeaderSlot() {
return !!this.$slots.header;
},
hasFooterSlot() {
return !!this.$slots.footer;
},
/*
* Show the input field if a maxtags hasn't been set or reached.
*/
hasInput() {
return this.maxtags == null || this.maxtags === 1 || this.tagsLength < this.maxtags;
},
tagsLength() {
return this.tags.length;
},
/*
* If Taginput has onPasteSeparators prop,
* returning new RegExp used to split pasted string.
*/
separatorsAsRegExp() {
const sep = this.onPasteSeparators;
return sep.length ? new RegExp(sep.map((s) => {
return s ? s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") : null;
}).join("|"), "g") : null;
},
disabledOrUndefined() {
return this.disabled || void 0;
}
},
watch: {
/*
* When v-model is changed set internal value.
*/
modelValue(value) {
this.tags = Array.isArray(value) ? value.slice(0) : value || [];
},
hasInput() {
if (!this.hasInput) this.onBlur();
}
},
methods: {
addTag(tag) {
const tagToAdd = tag || this.newTag.trim();
if (tagToAdd) {
if (!this.autocomplete) {
const reg = this.separatorsAsRegExp;
if (reg && tagToAdd.match(reg)) {
tagToAdd.split(reg).map((t) => t.trim()).filter((t) => t.length !== 0).map(this.addTag);
return;
}
}
const add = !this.allowDuplicates ? this.tags.indexOf(tagToAdd) === -1 : true;
if (add && this.beforeAdding(tagToAdd)) {
if (this.maxtags === 1) {
this.tags = [];
}
this.tags.push(this.createTag(tagToAdd));
this.$emit("update:modelValue", this.tags);
this.$emit("add", tagToAdd);
}
this.requestID = requestAnimationFrame(() => {
this.newTag = "";
this.$emit("typing", "");
});
}
},
getNormalizedTagText(tag) {
if (typeof tag === "object") {
tag = helpers.getValueByPath(tag, this.field);
}
return `${tag}`;
},
customOnBlur(event) {
if (!this.autocomplete) this.addTag();
this.onBlur(event);
},
onSelect(option) {
if (!option) return;
this.addTag(option);
this.$nextTick(() => {
this.newTag = "";
});
},
removeTag(index, event) {
const tag = this.tags.splice(index, 1)[0];
this.$emit("update:modelValue", this.tags);
this.$emit("remove", tag);
if (event) event.stopPropagation();
if (this.openOnFocus && this.$refs.autocomplete) {
this.$refs.autocomplete.focus();
}
return tag;
},
removeLastTag() {
if (this.tagsLength > 0) {
this.removeTag(this.tagsLength - 1);
}
},
keydown(event) {
const { key } = event;
if (this.removeOnKeys.indexOf(key) !== -1 && !this.newTag.length) {
this.removeLastTag();
}
if (this.autocomplete && !this.allowNew) return;
if (this.confirmKeys.indexOf(key) >= 0) {
if (key !== "Tab") event.preventDefault();
if (key === "Enter" && this.isComposing) return;
this.addTag();
}
},
onTyping(event) {
this.$emit("typing", typeof event === "number" ? event : event == null ? void 0 : event.trim());
},
emitInfiniteScroll() {
this.$emit("infinite-scroll");
}
},
beforeUnmount() {
cancelAnimationFrame(this.requestID);
}
});
const _hoisted_1 = ["disabled"];
const _hoisted_2 = {
key: 0,
class: "help counter"
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_b_tag = vue.resolveComponent("b-tag");
const _component_b_autocomplete = vue.resolveComponent("b-autocomplete");
return vue.openBlock(), vue.createElementBlock(
"div",
vue.mergeProps({
class: ["taginput control", _ctx.rootClasses]
}, _ctx.rootAttrs),
[
vue.createElementVNode("div", {
class: vue.normalizeClass(["taginput-container input", [_ctx.statusType, _ctx.size, _ctx.containerClasses]]),
disabled: _ctx.disabledOrUndefined,
onClick: _cache[3] || (_cache[3] = ($event) => _ctx.hasInput && _ctx.focus())
}, [
vue.renderSlot(_ctx.$slots, "selected", { tags: _ctx.tags }, () => [
(vue.openBlock(true), vue.createElementBlock(
vue.Fragment,
null,
vue.renderList(_ctx.tags, (tag, index) => {
return vue.openBlock(), vue.createBlock(_component_b_tag, {
key: _ctx.getNormalizedTagText(tag) + index,
type: _ctx.type,
"close-type": _ctx.closeType,
size: _ctx.size,
rounded: _ctx.rounded,
attached: _ctx.attached,
tabstop: false,
disabled: _ctx.disabledOrUndefined,
ellipsis: _ctx.ellipsis,
closable: _ctx.closable,
"aria-close-label": _ctx.ariaCloseLabel,
title: _ctx.ellipsis && _ctx.getNormalizedTagText(tag),
onClose: ($event) => _ctx.removeTag(index, $event)
}, {
default: vue.withCtx(() => [
vue.renderSlot(_ctx.$slots, "tag", { tag }, () => [
vue.createTextVNode(
vue.toDisplayString(_ctx.getNormalizedTagText(tag)),
1
/* TEXT */
)
])
]),
_: 2
/* DYNAMIC */
}, 1032, ["type", "close-type", "size", "rounded", "attached", "disabled", "ellipsis", "closable", "aria-close-label", "title", "onClose"]);
}),
128
/* KEYED_FRAGMENT */
))
]),
_ctx.hasInput ? (vue.openBlock(), vue.createBlock(_component_b_autocomplete, vue.mergeProps({
key: 0,
ref: "autocomplete",
modelValue: _ctx.newTag,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => _ctx.newTag = $event)
}, _ctx.fallthroughAttrs, {
data: _ctx.data,
field: _ctx.field,
icon: _ctx.icon,
"icon-pack": _ctx.iconPack,
maxlength: _ctx.maxlength,
"has-counter": false,
size: _ctx.size,
disabled: _ctx.disabledOrUndefined,
loading: _ctx.loading,
autocomplete: _ctx.nativeAutocomplete,
"open-on-focus": _ctx.openOnFocus,
"keep-open": _ctx.keepOpen,
"keep-first": _ctx.keepFirst,
"group-field": _ctx.groupField,
"group-options": _ctx.groupOptions,
"use-html5-validation": _ctx.useHtml5Validation,
"check-infinite-scroll": _ctx.checkInfiniteScroll,
"append-to-body": _ctx.appendToBody,
"confirm-keys": _ctx.confirmKeys,
onTyping: _ctx.onTyping,
onFocus: _ctx.onFocus,
onBlur: _ctx.customOnBlur,
onKeydown: _ctx.keydown,
onCompositionstart: _cache[1] || (_cache[1] = ($event) => _ctx.isComposing = true),
onCompositionend: _cache[2] || (_cache[2] = ($event) => _ctx.isComposing = false),
onSelect: _ctx.onSelect,
onInfiniteScroll: _ctx.emitInfiniteScroll
}), vue.createSlots({
_: 2
/* DYNAMIC */
}, [
_ctx.hasHeaderSlot ? {
name: "header",
fn: vue.withCtx(() => [
vue.renderSlot(_ctx.$slots, "header")
]),
key: "0"
} : void 0,
_ctx.hasDefaultSlot ? {
name: "default",
fn: vue.withCtx((props) => [
vue.renderSlot(_ctx.$slots, "default", {
option: props.option,
index: props.index
})
]),
key: "1"
} : void 0,
_ctx.hasEmptySlot ? {
name: "empty",
fn: vue.withCtx(() => [
vue.renderSlot(_ctx.$slots, "empty")
]),
key: "2"
} : void 0,
_ctx.hasFooterSlot ? {
name: "footer",
fn: vue.withCtx(() => [
vue.renderSlot(_ctx.$slots, "footer")
]),
key: "3"
} : void 0
]), 1040, ["modelValue", "data", "field", "icon", "icon-pack", "maxlength", "size", "disabled", "loading", "autocomplete", "open-on-focus", "keep-open", "keep-first", "group-field", "group-options", "use-html5-validation", "check-infinite-scroll", "append-to-body", "confirm-keys", "onTyping", "onFocus", "onBlur", "onKeydown", "onSelect", "onInfiniteScroll"])) : vue.createCommentVNode("v-if", true)
], 10, _hoisted_1),
_ctx.hasCounter && (_ctx.maxtags || _ctx.maxlength) ? (vue.openBlock(), vue.createElementBlock("small", _hoisted_2, [
_ctx.maxlength && _ctx.valueLength > 0 ? (vue.openBlock(), vue.createElementBlock(
vue.Fragment,
{ key: 0 },
[
vue.createTextVNode(
vue.toDisplayString(_ctx.valueLength) + " / " + vue.toDisplayString(_ctx.maxlength),
1
/* TEXT */
)
],
64
/* STABLE_FRAGMENT */
)) : _ctx.maxtags ? (vue.openBlock(), vue.createElementBlock(
vue.Fragment,
{ key: 1 },
[
vue.createTextVNode(
vue.toDisplayString(_ctx.tagsLength) + " / " + vue.toDisplayString(_ctx.maxtags),
1
/* TEXT */
)
],
64
/* STABLE_FRAGMENT */
)) : vue.createCommentVNode("v-if", true)
])) : vue.createCommentVNode("v-if", true)
],
16
/* FULL_PROPS */
);
}
var Taginput = /* @__PURE__ */ _pluginVue_exportHelper._export_sfc(_sfc_main, [["render", _sfc_render]]);
const Plugin = {
install(Vue) {
plugins.registerComponent(Vue, Taginput);
}
};
exports.BTaginput = Taginput;
exports.default = Plugin;