UNPKG

@ishitatsuyuki/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

562 lines (547 loc) 19 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var vue = require('vue'); var helpers = require('./helpers.js'); var config = require('./config.js'); var BaseComponentMixin = require('./BaseComponentMixin-a03c02e3.js'); var Icon = require('./Icon-172f9998.js'); var plugins = require('./plugins-5849434f.js'); var InstanceRegistry = require('./InstanceRegistry-14c98540.js'); var MessageMixin = { components: { [Icon.script.name]: Icon.script }, props: { /** Whether modal is active or not, use the .sync modifier (Vue 2.x) or v-model:active (Vue 3.x) to make it two-way binding */ active: { type: Boolean, default: true }, /** Adds an 'X' button that closes the notification. */ closable: { type: Boolean, default: false }, /** Message text (can contain HTML). */ message: String, /** Type (color) of the notification, optional. */ type: String, /** Adds an icon on the left side depending on the type (or the icon prop if defined). */ hasIcon: Boolean, /** Icon name to use with has-icon. */ icon: String, /** Icon pack to use. */ iconPack: String, /** Icon size */ iconSize: { type: String, default: 'large' }, /** Hide notification after duration only not programmatic. */ autoClose: { type: Boolean, default: false }, /** Visibility duration in miliseconds. */ duration: { type: Number, default: 2000 } }, data() { return { isActive: this.active }; }, watch: { active(value) { this.isActive = value; }, isActive(value) { if (value) { this.setAutoClose(); } else { if (this.timer) { clearTimeout(this.timer); } } } }, computed: { /** * Icon name (MDI) based on type. */ computedIcon() { if (this.icon) { return this.icon; } switch (this.type) { case 'info': return 'information'; case 'success': return 'check-circle'; case 'warning': return 'alert'; case 'danger': return 'alert-circle'; default: return null; } } }, methods: { /** * Close the Message and emit events. */ close() { this.isActive = false; this.$emit('close', ...arguments); this.$emit('update:active', false); }, /** * Set timer to auto close message */ setAutoClose() { if (this.autoClose) { this.timer = setTimeout(() => { if (this.isActive) { this.close({ action: 'close', method: 'timeout' }); } }, this.duration); } } }, mounted() { this.setAutoClose(); } }; /** * Bold notification blocks to alert your users of something * @displayName Notification * @requires ./NotificationNotice.vue * @style _notification.scss */ var script = { name: 'ONotification', configField: 'notification', mixins: [BaseComponentMixin.BaseComponentMixin, MessageMixin], emits: ['update:active', 'close'], props: { /** * Which position the notification will appear when programmatically * @values top-right, top, top-left, bottom-right, bottom, bottom-left */ position: String, /** * Color of the control, optional * @values primary, info, success, warning, danger, and any other custom color */ variant: [String, Object], /** * Label for the close button, to be read by accessibility screenreaders. */ ariaCloseLabel: String, /** * Size of close icon */ closeIconSize: { type: String, default: 'small' }, /** * Custom animation (transition name). */ animation: { type: String, default: 'fade' }, /** Component to be injected, used to open a component modal programmatically. Close modal within the component by emitting a 'close' event — this.$emit('close') */ component: [Object, Function], /** Props to be binded to the injected component */ props: Object, /** Events to be binded to the injected component */ events: { type: Object, default: () => ({}) }, /** Close icon name */ closeIcon: { type: String, default: () => { return helpers.getValueByPath(config.getOptions(), 'notification.closeIcon', 'close'); } }, rootClass: [String, Function, Array], closeClass: [String, Function, Array], contentClass: [String, Function, Array], iconClass: [String, Function, Array], positionClass: [String, Function, Array], variantClass: [String, Function, Array], wrapperClass: [String, Function, Array], }, computed: { rootClasses() { return [ this.computedClass('rootClass', 'o-notification'), { [this.computedClass('variantClass', 'o-notification--', this.variant)]: this.variant }, { [this.computedClass('positionClass', 'o-notification--', this.position)]: this.position }, ]; }, wrapperClasses() { return [ this.computedClass('wrapperClass', 'o-notification__wrapper') ]; }, iconClasses() { return [ this.computedClass('iconClass', 'o-notification__icon') ]; }, contentClasses() { return [ this.computedClass('contentClass', 'o-notification__content') ]; }, closeClasses() { return [ this.computedClass('closeClass', 'o-notification__close') ]; }, }, }; function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_o_icon = vue.resolveComponent("o-icon"); return vue.openBlock(), vue.createBlock(vue.Transition, { name: $props.animation }, { default: vue.withCtx(() => [vue.withDirectives(vue.createVNode("article", { class: $options.rootClasses }, [_ctx.closable ? (vue.openBlock(), vue.createBlock("button", { key: 0, class: $options.closeClasses, type: "button", onClick: _cache[1] || (_cache[1] = $event => _ctx.close({ action: 'close', method: 'x' })), "aria-label": $props.ariaCloseLabel }, [vue.createVNode(_component_o_icon, { clickable: "", pack: _ctx.iconPack, both: "", icon: $props.closeIcon, size: $props.closeIconSize }, null, 8 /* PROPS */ , ["pack", "icon", "size"])], 10 /* CLASS, PROPS */ , ["aria-label"])) : vue.createCommentVNode("v-if", true), $props.component ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent($props.component), vue.mergeProps({ key: 1 }, $props.props, vue.toHandlers($props.events), { onClose: _ctx.close }), null, 16 /* FULL_PROPS */ , ["onClose"])) : vue.createCommentVNode("v-if", true), _ctx.$slots.default || _ctx.message ? (vue.openBlock(), vue.createBlock("div", { key: 2, class: $options.wrapperClasses }, [_ctx.computedIcon ? vue.createVNode(_component_o_icon, { key: 0, icon: _ctx.computedIcon, pack: _ctx.iconPack, class: $options.iconClasses, both: "", size: _ctx.iconSize, "aria-hidden": "" }, null, 8 /* PROPS */ , ["icon", "pack", "class", "size"]) : vue.createCommentVNode("v-if", true), vue.createVNode("div", { class: $options.contentClasses }, [_ctx.message ? (vue.openBlock(), vue.createBlock("span", { key: 0, innerHTML: _ctx.message }, null, 8 /* PROPS */ , ["innerHTML"])) : vue.renderSlot(_ctx.$slots, "default", { key: 1, closeNotification: _ctx.close })], 2 /* CLASS */ )], 2 /* CLASS */ )) : vue.createCommentVNode("v-if", true)], 2 /* CLASS */ ), [[vue.vShow, _ctx.isActive]])]), _: 1 }, 8 /* PROPS */ , ["name"]); } script.render = render; script.__file = "src/components/notification/Notification.vue"; var NoticeMixin = { props: { /** Type (color) of the notification, optional. */ type: { type: String, }, /** Message text (can contain HTML). */ message: [String, Array], /** Visibility duration in miliseconds. */ duration: { type: Number, default: () => { return helpers.getValueByPath(config.getOptions(), 'notification.duration', 1000); } }, /** If should queue with others notices (snackbar/toast/notification). */ queue: { type: Boolean, default: () => { return helpers.getValueByPath(config.getOptions(), 'notification.noticeQueue', undefined); } }, /** Show the Notification indefinitely until it is dismissed when programmatically. */ indefinite: { type: Boolean, default: false }, /** Which position the notification will appear when programmatically. */ position: { type: String, default: 'top', validator(value) { return [ 'top-right', 'top', 'top-left', 'bottom-right', 'bottom', 'bottom-left' ].indexOf(value) > -1; } }, /** DOM element the toast will be created on. Note that this also changes the position of the toast from fixed to absolute. Meaning that the container should be fixed. */ container: { type: String, default: () => { return helpers.getValueByPath(config.getOptions(), 'notification.containerElement', undefined); } }, /** @ignore */ programmatic: Object, /** @ignore */ promise: Promise, /** Callback function to call after close (programmatically close or user canceled) */ onClose: { type: Function, default: () => { } } }, data() { return { isActive: false, parentTop: null, parentBottom: null, newDuration: this.duration, newContainer: this.container }; }, computed: { correctParent() { switch (this.position) { case 'top-right': case 'top': case 'top-left': return this.parentTop; case 'bottom-right': case 'bottom': case 'bottom-left': return this.parentBottom; } }, transition() { switch (this.position) { case 'top-right': case 'top': case 'top-left': return { enter: 'fadeInDown', leave: 'fadeOut' }; case 'bottom-right': case 'bottom': case 'bottom-left': return { enter: 'fadeInUp', leave: 'fadeOut' }; } } }, methods: { shouldQueue() { if (!this.queue) return false; return (this.parentTop.childElementCount > 0 || this.parentBottom.childElementCount > 0); }, close() { clearTimeout(this.timer); this.$emit('close'); this.onClose.apply(null, arguments); if (this.programmatic) { if (this.programmatic.instances) { this.programmatic.instances.remove(this); } if (this.programmatic.resolve) { this.programmatic.resolve.apply(null, arguments); } } // Timeout for the animation complete before destroying setTimeout(() => { this.isActive = false; helpers.removeElement(this.$el); }, 150); }, showNotice() { if (this.shouldQueue()) this.correctParent.innerHTML = ''; this.correctParent.insertAdjacentElement('afterbegin', this.$el); this.isActive = true; if (!this.indefinite) { this.timer = setTimeout(() => this.timeoutCallback(), this.newDuration); } }, setupContainer() { this.parentTop = document.querySelector((this.newContainer ? this.newContainer : 'body') + `>.${this.rootClasses().join('.')}.${this.positionClasses('top').join('.')}`); this.parentBottom = document.querySelector((this.newContainer ? this.newContainer : 'body') + `>.${this.rootClasses().join('.')}.${this.positionClasses('bottom').join('.')}`); if (this.parentTop && this.parentBottom) return; if (!this.parentTop) { this.parentTop = document.createElement('div'); this.parentTop.className = `${this.rootClasses().join(' ')} ${this.positionClasses('top').join(' ')}`; } if (!this.parentBottom) { this.parentBottom = document.createElement('div'); this.parentBottom.className = `${this.rootClasses().join(' ')} ${this.positionClasses('bottom').join(' ')}`; } const container = document.querySelector(this.newContainer) || document.body; container.appendChild(this.parentTop); container.appendChild(this.parentBottom); if (this.newContainer) { this.parentTop.classList.add('has-custom-container'); this.parentBottom.classList.add('has-custom-container'); } }, timeoutCallback() { return this.close({ action: 'close', method: 'timeout' }); } }, beforeMount() { this.setupContainer(); }, mounted() { if (this.programmatic && this.programmatic.instances) { this.programmatic.instances.add(this); } this.showNotice(); } }; /** * @displayName Notification Notice */ var script$1 = vue.defineComponent({ name: 'ONotificationNotice', configField: 'notification', mixins: [BaseComponentMixin.BaseComponentMixin, NoticeMixin], props: { propsNotification: Object, noticeClass: [String, Function, Array], noticePositionClass: [String, Function, Array] }, emits: ['update:active', 'close'], methods: { rootClasses() { return [ this.computedClass('noticeClass', 'o-notices'), ]; }, positionClasses(position) { return [ this.computedClass('noticePositionClass', 'o-notices--', position), ]; }, timeoutCallback() { return this.$refs.notification.close({ action: 'close', method: 'timeout' }); } } }); function render$1(_ctx, _cache, $props, $setup, $data, $options) { const _component_o_notification = vue.resolveComponent("o-notification"); return vue.openBlock(), vue.createBlock(_component_o_notification, vue.mergeProps(_ctx.propsNotification, { ref: "notification", onClose: _ctx.close }), { default: vue.withCtx(() => [vue.renderSlot(_ctx.$slots, "default")]), _: 3 }, 16 /* FULL_PROPS */ , ["onClose"]); } script$1.render = render$1; script$1.__file = "src/components/notification/NotificationNotice.vue"; let localVueInstance; let instances = new InstanceRegistry.InstanceRegistry(); const NotificationProgrammatic = { open(params) { let newParams; if (typeof params === 'string') { newParams = { message: params }; } else { newParams = params; } const defaultParam = { programmatic: { instances }, position: helpers.getValueByPath(config.getOptions(), 'notification.position', 'top-right'), closable: params.closable || helpers.getValueByPath(config.getOptions(), 'notification.closable', false) }; let slot; if (Array.isArray(newParams.message)) { slot = newParams.message; delete newParams.message; } newParams.active = true; const propsData = helpers.merge(defaultParam, newParams); propsData.promise = new Promise((p1, p2) => { propsData.programmatic.resolve = p1; propsData.programmatic.reject = p2; }); const app = localVueInstance || config.VueInstance; propsData.propsNotification = Object.assign({}, propsData); propsData.propsNotification.isActive = true; const defaultSlot = () => { return newParams.message; }; const vnode = vue.createVNode(script$1, propsData, defaultSlot); vnode.appContext = app._context; vue.render(vnode, document.createElement('div')); return vnode.component.proxy; }, closeAll() { instances.walk((entry) => { entry.close(...arguments); }); } }; var index = { install(app) { localVueInstance = app; plugins.registerComponent(app, script); plugins.registerComponentProgrammatic(app, 'notification', NotificationProgrammatic); } }; exports.NotificationProgrammatic = NotificationProgrammatic; exports.ONotification = script; exports.default = index;