UNPKG

@adamdehaven/vue-custom-tooltip

Version:

A customizable, reusable, and reactive tooltip component for Vue (and VuePress) projects.

392 lines (364 loc) 16.1 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); // // // // // // // // // // // // // // // // // // // // // // var script = { name: 'VueCustomTooltip', props: { label: String, active: { type: Boolean, default: true, }, sticky: Boolean, // Always showing multiline: Boolean, // Multiple lines underlined: Boolean, abbreviation: Boolean, position: { type: String, default: 'is-top', validator: function validator(value) { return ['is-top', 'is-bottom', 'is-left', 'is-right'].indexOf(value) > -1 }, }, size: { type: String, default: 'is-medium', validator: function validator(value) { return ['is-small', 'is-medium', 'is-large'].indexOf(value) > -1 }, }, }, data: function data() { return { labelText: this.label || null, isActive: this.active || true, isSticky: this.sticky || false, isMultiline: this.multiline || false, isUnderlined: this.underlined || false, isAbbreviation: this.abbreviation || false, hasPosition: this.position || 'is-top', hasSize: this.size || 'is-medium', } }, computed: { dynamicStyles: function dynamicStyles() { return { '--vue-custom-tooltip-color': this.$vueCustomTooltip && this.$vueCustomTooltip.hasOwnProperty('color') ? this.$vueCustomTooltip.color : null, '--vue-custom-tooltip-background': this.$vueCustomTooltip && this.$vueCustomTooltip.hasOwnProperty('background') ? this.$vueCustomTooltip.background : null, '--vue-custom-tooltip-border-radius': this.$vueCustomTooltip && this.$vueCustomTooltip.hasOwnProperty('borderRadius') ? this.$vueCustomTooltip.borderRadius : null, '--vue-custom-tooltip-font-weight': this.$vueCustomTooltip && this.$vueCustomTooltip.hasOwnProperty('fontWeight') ? this.$vueCustomTooltip.fontWeight : null, } }, }, watch: { label: { handler: function handler(value) { this.labelText = value; }, immediate: true, }, active: { handler: function handler(value) { this.isActive = value; }, immediate: true, }, sticky: { handler: function handler(value) { this.isSticky = value; }, immediate: true, }, multiline: { handler: function handler(value) { this.isMultiline = value; }, immediate: true, }, underlined: { handler: function handler(value) { this.isUnderlined = value; }, immediate: true, }, abbreviation: { handler: function handler(value) { this.isAbbreviation = value; }, immediate: true, }, position: { handler: function handler(value) { this.hasPosition = value; }, immediate: true, }, size: { handler: function handler(value) { this.hasSize = value; }, immediate: true, }, }, }; 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 (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 (context) { style.call(this, createInjectorShadow(context, 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; } function createInjectorSSR(context) { if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { context = __VUE_SSR_CONTEXT__; } if (!context) { return function () { }; } if (!('styles' in context)) { context._styles = context._styles || {}; Object.defineProperty(context, 'styles', { enumerable: true, get: function () { return context._renderStyles(context._styles); } }); context._renderStyles = context._renderStyles || renderStyles; } return function (id, style) { return addStyle(id, style, context); }; } function addStyle(id, css, context) { var group = process.env.NODE_ENV === 'production' ? css.media || 'default' : id; var style = context._styles[group] || (context._styles[group] = { ids: [], css: '' }); if (!style.ids.includes(id)) { style.media = css.media; style.ids.push(id); var code = css.source; if (process.env.NODE_ENV !== 'production' && css.map) { // https://developer.chrome.com/devtools/docs/javascript-debugging // this makes source maps inside style tags work properly in Chrome code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 code += '\n/*# sourceMappingURL=data:application/json;base64,' + Buffer.from(unescape(encodeURIComponent(JSON.stringify(css.map)))).toString('base64') + ' */'; } style.css += code + '\n'; } } function renderStyles(styles) { var css = ''; for (var key in styles) { var style = styles[key]; css += '<style data-vue-ssr-id="' + Array.from(style.ids).join(' ') + '"' + (style.media ? ' media="' + style.media + '"' : '') + '>' + style.css + '</style>'; } return css; } /* script */ var __vue_script__ = script; /* template */ var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c(_vm.isAbbreviation ? 'abbr' : 'span',{tag:"component",class:[ _vm.hasPosition, _vm.hasSize, { 'vue-custom-tooltip': _vm.isActive && _vm.labelText, 'is-sticky': _vm.isSticky, 'has-multiline': _vm.isMultiline, 'is-underlined': _vm.isUnderlined || _vm.isAbbreviation, } ],style:([_vm.dynamicStyles, { cursor: _vm.isAbbreviation ? 'help' : 'pointer' }]),attrs:{"data-label":_vm.labelText,"aria-label":_vm.labelText,"role":"tooltip"}},[_vm._t("default")],2)}; var __vue_staticRenderFns__ = []; /* style */ var __vue_inject_styles__ = function (inject) { if (!inject) { return } inject("data-v-60bf38c6_0", { source: ".vue-custom-tooltip{--vue-custom-tooltip-color:#fff;--vue-custom-tooltip-background:#000;--vue-custom-tooltip-border-radius:100px;--vue-custom-tooltip-font-weight:400}", map: undefined, media: undefined }) ,inject("data-v-60bf38c6_1", { source: ".vue-custom-tooltip{position:relative;display:inline-block;text-decoration-line:none!important}.vue-custom-tooltip.is-top:after,.vue-custom-tooltip.is-top:before{top:auto;right:auto;bottom:calc(100% + 5px + 2px);left:50%;transform:translateX(-50%)}.vue-custom-tooltip.is-top:before{border-top:5px solid #000;border-top:5px solid var(--vue-custom-tooltip-background);border-right:5px solid transparent;border-left:5px solid transparent;bottom:calc(100% + 2px)}.vue-custom-tooltip.is-top.has-multiline.is-small:after{width:140px}.vue-custom-tooltip.is-top.has-multiline.is-medium:after{width:250px;padding:.6rem 1.25rem .65rem}.vue-custom-tooltip.is-top.has-multiline.is-large:after{width:480px;padding:0.6rem 1rem 0.65rem}.vue-custom-tooltip.is-right:after,.vue-custom-tooltip.is-right:before{top:50%;right:auto;bottom:auto;left:calc(100% + 5px + 2px);transform:translateY(-50%)}.vue-custom-tooltip.is-right:before{border-top:5px solid transparent;border-right:5px solid #000;border-right:5px solid var(--vue-custom-tooltip-background);border-bottom:5px solid transparent;left:calc(100% + 2px)}.vue-custom-tooltip.is-right.has-multiline.is-small:after{width:140px}.vue-custom-tooltip.is-right.has-multiline.is-medium:after{width:250px;padding:.6rem 1.25rem .65rem}.vue-custom-tooltip.is-right.has-multiline.is-large:after{width:480px;padding:0.6rem 1rem 0.65rem}.vue-custom-tooltip.is-bottom:after,.vue-custom-tooltip.is-bottom:before{top:calc(100% + 5px + 2px);right:auto;bottom:auto;left:50%;transform:translateX(-50%)}.vue-custom-tooltip.is-bottom:before{border-right:5px solid transparent;border-bottom:5px solid #000;border-bottom:5px solid var(--vue-custom-tooltip-background);border-left:5px solid transparent;top:calc(100% + 2px)}.vue-custom-tooltip.is-bottom.has-multiline.is-small:after{width:140px}.vue-custom-tooltip.is-bottom.has-multiline.is-medium:after{width:250px;padding:.6rem 1.25rem .65rem}.vue-custom-tooltip.is-bottom.has-multiline.is-large:after{width:480px;padding:0.6rem 1rem 0.65rem}.vue-custom-tooltip.is-left:after,.vue-custom-tooltip.is-left:before{top:50%;right:calc(100% + 5px + 2px);bottom:auto;left:auto;transform:translateY(-50%)}.vue-custom-tooltip.is-left:before{border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000;border-left:5px solid var(--vue-custom-tooltip-background);right:calc(100% + 2px)}.vue-custom-tooltip.is-left.has-multiline.is-small:after{width:140px}.vue-custom-tooltip.is-left.has-multiline.is-medium:after{width:250px;padding:.6rem 1.25rem .65rem}.vue-custom-tooltip.is-left.has-multiline.is-large:after{width:480px;padding:0.6rem 1rem 0.65rem}.vue-custom-tooltip.is-underlined{border-bottom:1px dotted #000;border-bottom:1px dotted var(--vue-custom-tooltip-background);line-height:1.2}.vue-custom-tooltip:after,.vue-custom-tooltip:before{position:absolute;content:'';opacity:0;visibility:hidden;pointer-events:none;transition:opacity 86ms ease-out,visibility 86ms ease-out}.vue-custom-tooltip:before{z-index:889}.vue-custom-tooltip:after{content:attr(data-label);color:#fff;color:var(--vue-custom-tooltip-color);background:#000;background:var(--vue-custom-tooltip-background);width:auto;max-width:100vw;padding:.35rem .75rem .45rem;border-radius:100px;border-radius:var(--vue-custom-tooltip-border-radius);font-size:.85rem!important;font-weight:400;font-weight:var(--vue-custom-tooltip-font-weight);line-height:1.3;letter-spacing:normal!important;text-transform:none;box-shadow:0 1px 2px 1px rgba(0,1,0,.2);z-index:888;white-space:nowrap}.vue-custom-tooltip:not([data-label='']):hover:after,.vue-custom-tooltip:not([data-label='']):hover:before{opacity:1;visibility:visible}:disabled .vue-custom-tooltip{pointer-events:none}.vue-custom-tooltip:not([data-label='']).is-sticky:after,.vue-custom-tooltip:not([data-label='']).is-sticky:before{opacity:1;visibility:visible}.vue-custom-tooltip.has-multiline:after{display:block;padding:.5rem .75rem .65rem;text-align:center;line-height:1.4;white-space:pre-wrap}", map: undefined, media: undefined }); }; /* scoped */ var __vue_scope_id__ = undefined; /* module identifier */ var __vue_module_identifier__ = "data-v-60bf38c6"; /* functional template */ var __vue_is_functional_template__ = false; /* style inject shadow dom */ var __vue_component__ = /*#__PURE__*/normalizeComponent( { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, false, undefined, createInjectorSSR, undefined ); // Import vue component var defaultOptions = { name: 'VueCustomTooltip', color: '#fff', background: '#000', borderRadius: 12, fontWeight: 400, }; // Declare install function executed by Vue.use() var install = function installMyComponent(Vue, opt) { // Don't install if already installed, or SSR if (install.installed || Vue.prototype.$isServer) { return } install.installed = true; // Grab user options var userOptions = Object.assign({}, opt); // HEX regex: Hash, plus 3 or 6 valid characters var hexRegex = /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/; // Test color for valid HEX if (userOptions.hasOwnProperty('color') && !hexRegex.test(userOptions.color)) { delete userOptions.color; } // Test background for valid HEX if (userOptions.hasOwnProperty('background') && !hexRegex.test(userOptions.background)) { delete userOptions.background; } // borderRadius regex: number between 1-9, then any other numbers var borderRadiusRegex = /^[0-9]+$/; // Test borderRadius for integer if (userOptions.hasOwnProperty('borderRadius') && !borderRadiusRegex.test(userOptions.borderRadius)) { delete userOptions.borderRadius; } // fontWeight regex: number between 1-9 followed by two zeros var fontWeightRegex = /^[1-9]{1}00$/; // Test fontWeight for integer if (userOptions.hasOwnProperty('fontWeight') && !fontWeightRegex.test(userOptions.fontWeight)) { delete userOptions.fontWeight; } // Merge options var options = Object.assign({}, defaultOptions, userOptions); // Mutate borderRadius options.borderRadius = options.borderRadius + 'px'; // Add global property (mainly for passing styles) Vue.prototype.$vueCustomTooltip = options; // Register component, using options.name. // e.g. <VueCustomTooltip> Vue.component(options.name, __vue_component__); }; // Create module definition for Vue.use() var plugin = { install: install, }; // Auto-install when vue is found (eg. in browser via <script> tag) var GlobalVue = null; if (typeof window !== 'undefined') { GlobalVue = window.Vue; } else if (typeof global !== 'undefined') { GlobalVue = global.Vue; } if (GlobalVue) { GlobalVue.use(plugin, defaultOptions); } // Inject install function into component - allows component // to be registered via Vue.use() as well as Vue.component() __vue_component__.install = install; exports.default = __vue_component__;