@tsaibot/vue-typed
Version:
Typed components for VueJs
323 lines (283 loc) • 10.1 kB
JavaScript
import Vue from 'vue';
var script = Vue.extend({
name: 'VueTyped',
// vue component name
props: {
timeTakes: {
type: Number,
validator: value => value >= 0.0,
default: 2000
},
text: {
type: [String, Array],
required: true,
validator: value => {
var result = value != undefined && value != null && value.length > 0;
if (result && Array.isArray(value)) {
value.forEach(v => {
if (typeof v != 'string') {
result = false;
}
});
}
return result;
}
},
tag: {
type: String,
default: 'span',
validator: value => ['p', 'h1', 'h2', 'h3', 'h4', 'span'].includes(value)
}
},
data() {
return {
isDone: false,
arrayIndex: 0,
bindingText: ''
};
},
methods: {
async writeInit() {
if (typeof this.text === "string") {
await this.writeText(this.text);
await this.delay(this.timeTakes);
this.isDone = true;
} else {
if (Array.isArray(this.text)) {
this.setIntervalImmediately(async () => await this.managerArray(), this.timeTakes * 1.4 * 2);
}
}
},
async writeText(text) {
let index = 0;
this.bindingText = '';
const period = this.timeTakes / text.length;
const timer = setInterval(() => {
if (index >= text.length - 1) {
clearInterval(timer);
}
index = this.appendText(text[index], index);
}, period);
},
appendText(char, index) {
this.bindingText += char;
index++;
return index;
},
async eraseText(text) {
let index = text.length;
this.bindingText = text;
const period = this.timeTakes / text.length;
const timer = setInterval(() => {
if (index <= 0) {
clearInterval(timer);
}
index = this.removeText(index);
}, period);
},
removeText(index) {
this.bindingText = this.bindingText.substring(0, index);
index--;
return index;
},
async managerArray() {
const text = this.text;
await this.writeText(text[this.arrayIndex]);
await this.delay(this.timeTakes * 1.5);
await this.eraseText(text[this.arrayIndex]);
if (this.arrayIndex >= this.text.length - 1) {
this.arrayIndex = 0;
} else {
this.arrayIndex++;
}
return;
},
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},
setIntervalImmediately(func, interval) {
func();
return setInterval(func, interval);
}
},
async mounted() {
await this.writeInit();
}
});
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.
const 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;
}
let 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
const originalRender = options.render;
options.render = function renderWithStyleInjection(h, context) {
hook.call(context);
return originalRender(h, context);
};
}
else {
// inject component registration as beforeCreate hook
const existing = options.beforeCreate;
options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
}
}
return script;
}
const isOldIE = typeof navigator !== 'undefined' &&
/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
function createInjector(context) {
return (id, style) => addStyle(id, style);
}
let HEAD;
const styles = {};
function addStyle(id, css) {
const group = isOldIE ? css.media || 'default' : id;
const style = styles[group] || (styles[group] = { ids: new Set(), styles: [] });
if (!style.ids.has(id)) {
style.ids.add(id);
let code = css.source;
if (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,' +
btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) +
' */';
}
if (!style.element) {
style.element = document.createElement('style');
style.element.type = 'text/css';
if (css.media)
style.element.setAttribute('media', css.media);
if (HEAD === undefined) {
HEAD = document.head || document.getElementsByTagName('head')[0];
}
HEAD.appendChild(style.element);
}
if ('styleSheet' in style.element) {
style.styles.push(code);
style.element.styleSheet.cssText = style.styles
.filter(Boolean)
.join('\n');
}
else {
const index = style.ids.size - 1;
const textNode = document.createTextNode(code);
const nodes = style.element.childNodes;
if (nodes[index])
style.element.removeChild(nodes[index]);
if (nodes.length)
style.element.insertBefore(textNode, nodes[index]);
else
style.element.appendChild(textNode);
}
}
}
/* 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(_vm.tag, {
tag: "component"
}, [_c('span', {
staticClass: "vue-typed"
}, [_vm._v(_vm._s(_vm.bindingText))]), _vm._v(" "), !_vm.isDone ? _c('span', {
staticClass: "caret"
}) : _vm._e()]);
};
var __vue_staticRenderFns__ = [];
/* style */
const __vue_inject_styles__ = function (inject) {
if (!inject) return;
inject("data-v-e5794ea6_0", {
source: ".caret[data-v-e5794ea6]{display:inline-block;vertical-align:baseline;width:1px;background:#000;margin-left:3px;position:relative;top:2px;-webkit-animation:caret-animation-data-v-e5794ea6 .5s linear infinite;animation:caret-animation-data-v-e5794ea6 .5s linear infinite}.caret[data-v-e5794ea6]:empty:before{content:\"\\200b\"}@keyframes caret-animation-data-v-e5794ea6{0%{opacity:1}30%{opacity:1}40%{opacity:0}90%{opacity:0}100%{opacity:1}}",
map: undefined,
media: undefined
});
};
/* scoped */
const __vue_scope_id__ = "data-v-e5794ea6";
/* module identifier */
const __vue_module_identifier__ = undefined;
/* functional template */
const __vue_is_functional_template__ = false;
/* style inject SSR */
/* style inject shadow dom */
const __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, createInjector, undefined, undefined);
// Import vue component
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// install function executed by Vue.use()
const install = function installVueTyped(Vue) {
if (install.installed) return;
install.installed = true;
Vue.component('VueTyped', __vue_component__);
}; // Create module definition for Vue.use()
// to be registered via Vue.use() as well as Vue.component()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
__vue_component__.install = install; // Export component by default
// also be used as directives, etc. - eg. import { RollupDemoDirective } from 'rollup-demo';
// export const RollupDemoDirective = component;
export default __vue_component__;