UNPKG

buefy

Version:

Lightweight UI components for Vue.js based on Bulma

502 lines (431 loc) 15.7 kB
/*! Buefy v0.8.2 | MIT License | github.com/buefy/buefy */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.Upload = {})); }(this, function (exports) { 'use strict'; var config = { defaultContainerElement: null, defaultIconPack: 'mdi', defaultIconComponent: null, defaultDialogConfirmText: null, defaultDialogCancelText: null, defaultSnackbarDuration: 3500, defaultSnackbarPosition: null, defaultToastDuration: 2000, defaultToastPosition: null, defaultNotificationDuration: 2000, defaultNotificationPosition: null, defaultTooltipType: 'is-primary', defaultTooltipAnimated: false, defaultTooltipDelay: 0, defaultInputAutocomplete: 'on', defaultDateFormatter: null, defaultDateParser: null, defaultDateCreator: null, defaultDayNames: null, defaultMonthNames: null, defaultFirstDayOfWeek: null, defaultUnselectableDaysOfWeek: null, defaultTimeFormatter: null, defaultTimeParser: null, defaultModalCanCancel: ['escape', 'x', 'outside', 'button'], defaultModalScroll: null, defaultDatepickerMobileNative: true, defaultTimepickerMobileNative: true, defaultNoticeQueue: true, defaultInputHasCounter: true, defaultTaginputHasCounter: true, defaultUseHtml5Validation: true, defaultDropdownMobileModal: true, defaultFieldLabelPosition: null, defaultDatepickerYearsRange: [-100, 3], defaultDatepickerNearbyMonthDays: true, defaultDatepickerNearbySelectableMonthDays: false, defaultDatepickerShowWeekNumber: false }; var config$1 = config; var FormElementMixin = { props: { size: String, expanded: Boolean, loading: Boolean, rounded: Boolean, icon: String, iconPack: String, // Native options to use in HTML5 validation autocomplete: String, maxlength: [Number, String], useHtml5Validation: { type: Boolean, default: function _default() { return config$1.defaultUseHtml5Validation; } }, validationMessage: String }, data: function data() { return { isValid: true, isFocused: false, newIconPack: this.iconPack || config$1.defaultIconPack }; }, computed: { /** * Find parent Field, max 3 levels deep. */ parentField: function parentField() { var parent = this.$parent; for (var i = 0; i < 3; i++) { if (parent && !parent.$data._isField) { parent = parent.$parent; } } return parent; }, /** * Get the type prop from parent if it's a Field. */ statusType: function statusType() { if (!this.parentField) return; if (!this.parentField.newType) return; if (typeof this.parentField.newType === 'string') { return this.parentField.newType; } else { for (var key in this.parentField.newType) { if (this.parentField.newType[key]) { return key; } } } }, /** * Get the message prop from parent if it's a Field. */ statusMessage: function statusMessage() { if (!this.parentField) return; return this.parentField.newMessage; }, /** * Fix icon size for inputs, large was too big */ iconSize: function iconSize() { switch (this.size) { case 'is-small': return this.size; case 'is-medium': return; case 'is-large': return this.newIconPack === 'mdi' ? 'is-medium' : ''; } } }, methods: { /** * Focus method that work dynamically depending on the component. */ focus: function focus() { var _this = this; if (this.$data._elementRef === undefined) return; this.$nextTick(function () { var el = _this.$el.querySelector(_this.$data._elementRef); if (el) el.focus(); }); }, onBlur: function onBlur($event) { this.isFocused = false; this.$emit('blur', $event); this.checkHtml5Validity(); }, onFocus: function onFocus($event) { this.isFocused = true; this.$emit('focus', $event); }, /** * Check HTML5 validation, set isValid property. * If validation fail, send 'is-danger' type, * and error message to parent if it's a Field. */ checkHtml5Validity: function checkHtml5Validity() { var _this2 = this; if (!this.useHtml5Validation) return; if (this.$refs[this.$data._elementRef] === undefined) return; var el = this.$el.querySelector(this.$data._elementRef); var type = null; var message = null; var isValid = true; if (!el.checkValidity()) { type = 'is-danger'; message = this.validationMessage || el.validationMessage; isValid = false; } this.isValid = isValid; this.$nextTick(function () { if (_this2.parentField) { // Set type only if not defined if (!_this2.parentField.type) { _this2.parentField.newType = type; } // Set message only if not defined if (!_this2.parentField.message) { _this2.parentField.newMessage = message; } } }); return this.isValid; } } }; // Polyfills for SSR var isSSR = typeof window === 'undefined'; var HTMLElement = isSSR ? Object : window.HTMLElement; var File = isSSR ? Object : window.File; // var script = { name: 'BUpload', mixins: [FormElementMixin], inheritAttrs: false, props: { value: { type: [Object, Function, File, Array] }, multiple: Boolean, disabled: Boolean, accept: String, dragDrop: Boolean, type: { type: String, default: 'is-primary' }, native: { type: Boolean, default: false } }, data: function data() { return { newValue: this.value, dragDropFocus: false, _elementRef: 'input' }; }, watch: { /** * When v-model is changed: * 1. Get value from input file * 2. Set internal value. * 3. Reset input value if array is empty or when input file is not found in newValue * 4. If it's invalid, validate again. */ value: function value(_value) { var inputFiles = this.$refs.input.files; this.newValue = _value; if (!this.newValue || Array.isArray(this.newValue) && this.newValue.length === 0 || !inputFiles[0] || Array.isArray(this.newValue) && !this.newValue.some(function (a) { return a.name === inputFiles[0].name; })) { this.$refs.input.value = null; } !this.isValid && !this.dragDrop && this.checkHtml5Validity(); } }, methods: { /** * Listen change event on input type 'file', * emit 'input' event and validate */ onFileChange: function onFileChange(event) { if (this.disabled || this.loading) return; if (this.dragDrop) { this.updateDragDropFocus(false); } var value = event.target.files || event.dataTransfer.files; if (value.length === 0) { if (!this.newValue) { return; } if (this.native) { this.newValue = null; } } else if (!this.multiple) { // only one element in case drag drop mode and isn't multiple if (this.dragDrop && value.length !== 1) return;else { var file = value[0]; if (this.checkType(file)) { this.newValue = file; } else if (this.newValue) { this.newValue = null; } else { return; } } } else { // always new values if native or undefined local var newValues = false; if (this.native || !this.newValue) { this.newValue = []; newValues = true; } for (var i = 0; i < value.length; i++) { var _file = value[i]; if (this.checkType(_file)) { this.newValue.push(_file); newValues = true; } } if (!newValues) { return; } } this.$emit('input', this.newValue); !this.dragDrop && this.checkHtml5Validity(); }, /** * Listen drag-drop to update internal variable */ updateDragDropFocus: function updateDragDropFocus(focus) { if (!this.disabled && !this.loading) { this.dragDropFocus = focus; } }, /** * Check mime type of file */ checkType: function checkType(file) { if (!this.accept) return true; var types = this.accept.split(','); if (types.length === 0) return true; var valid = false; for (var i = 0; i < types.length && !valid; i++) { var type = types[i].trim(); if (type) { if (type.substring(0, 1) === '.') { // check extension var extIndex = file.name.lastIndexOf('.'); var extension = extIndex >= 0 ? file.name.substring(extIndex) : ''; if (extension.toLowerCase() === type.toLowerCase()) { valid = true; } } else { // check mime type if (file.type.match(type)) { valid = true; } } } } return valid; } } }; function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */ , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { if (typeof shadowMode !== 'boolean') { createInjectorSSR = createInjector; createInjector = shadowMode; shadowMode = false; } // Vue.extend constructor export interop. var options = typeof script === 'function' ? script.options : script; // render functions if (template && template.render) { options.render = template.render; options.staticRenderFns = template.staticRenderFns; options._compiled = true; // functional template if (isFunctionalTemplate) { options.functional = true; } } // scopedId if (scopeId) { options._scopeId = scopeId; } var hook; if (moduleIdentifier) { // server build hook = function hook(context) { // 2.3 injection context = context || // cached call this.$vnode && this.$vnode.ssrContext || // stateful this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional // 2.2 with runInNewContext: true if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } // inject component styles if (style) { style.call(this, createInjectorSSR(context)); } // register component module identifier for async chunk inference if (context && context._registeredComponents) { context._registeredComponents.add(moduleIdentifier); } }; // used by ssr in case component is cached and beforeCreate // never gets called options._ssrRegister = hook; } else if (style) { hook = shadowMode ? function () { style.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); } : function (context) { style.call(this, createInjector(context)); }; } if (hook) { if (options.functional) { // register for functional component in vue file var originalRender = options.render; options.render = function renderWithStyleInjection(h, context) { hook.call(context); return originalRender(h, context); }; } else { // inject component registration as beforeCreate hook var existing = options.beforeCreate; options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; } } return script; } var normalizeComponent_1 = normalizeComponent; /* script */ const __vue_script__ = script; /* template */ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('label',{staticClass:"upload control"},[(!_vm.dragDrop)?[_vm._t("default")]:_c('div',{staticClass:"upload-draggable",class:[_vm.type, { 'is-loading': _vm.loading, 'is-disabled': _vm.disabled, 'is-hovered': _vm.dragDropFocus }],on:{"dragover":function($event){$event.preventDefault();_vm.updateDragDropFocus(true);},"dragleave":function($event){$event.preventDefault();_vm.updateDragDropFocus(false);},"dragenter":function($event){$event.preventDefault();_vm.updateDragDropFocus(true);},"drop":function($event){$event.preventDefault();_vm.onFileChange($event);}}},[_vm._t("default")],2),_vm._v(" "),_c('input',_vm._b({ref:"input",attrs:{"type":"file","multiple":_vm.multiple,"accept":_vm.accept,"disabled":_vm.disabled},on:{"change":_vm.onFileChange}},'input',_vm.$attrs,false))],2)}; var __vue_staticRenderFns__ = []; /* style */ const __vue_inject_styles__ = undefined; /* scoped */ const __vue_scope_id__ = undefined; /* module identifier */ const __vue_module_identifier__ = undefined; /* functional template */ const __vue_is_functional_template__ = false; /* style inject */ /* style inject SSR */ var Upload = normalizeComponent_1( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, undefined, undefined ); var use = function use(plugin) { if (typeof window !== 'undefined' && window.Vue) { window.Vue.use(plugin); } }; var registerComponent = function registerComponent(Vue, component) { Vue.component(component.name, component); }; var Plugin = { install: function install(Vue) { registerComponent(Vue, Upload); } }; use(Plugin); exports.Upload = Upload; exports.default = Plugin; Object.defineProperty(exports, '__esModule', { value: true }); }));