Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 8ea3208

Browse files
authored
Merge pull request #2 from ming-tsai/dev
chore: separete ts, vue and css
2 parents ae9489b + 58c6730 commit 8ea3208

File tree

6 files changed

+153
-157
lines changed

6 files changed

+153
-157
lines changed

build/rollup.config.js

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// rollup.config.js
21
import fs from 'fs';
32
import path from 'path';
43
import vue from 'rollup-plugin-vue';

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tsaibot/vue-typed",
3-
"version": "0.1.0-preview7",
3+
"version": "0.1.0-preview8",
44
"description": "Typed components for VueJs",
55
"repository": {
66
"type": "git",

src/vue-typed.css

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
.caret {
2+
display: inline-block;
3+
vertical-align: baseline;
4+
width: 1px;
5+
background: black;
6+
margin-left: 3px;
7+
position: relative;
8+
top: 2px;
9+
-webkit-animation: caret-animation 0.5s linear infinite;
10+
animation: caret-animation 0.5s linear infinite;
11+
}
12+
13+
.caret:empty:before {
14+
content: "\200b"; /* unicode zero width space character */
15+
}
16+
17+
@keyframes caret-animation {
18+
0% {
19+
opacity: 1;
20+
}
21+
30% {
22+
opacity: 1;
23+
}
24+
40% {
25+
opacity: 0;
26+
}
27+
90% {
28+
opacity: 0;
29+
}
30+
100% {
31+
opacity: 1;
32+
}
33+
}

src/vue-typed.ts

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import Vue from 'vue';
2+
3+
interface VueType {
4+
isDone: boolean;
5+
arrayIndex: number;
6+
bindingText: string;
7+
}
8+
9+
export default Vue.extend({
10+
name: 'VueTyped', // vue component name
11+
props: {
12+
timeTakes: {
13+
type: Number,
14+
validator: value => value >= 0.0,
15+
default: 2000
16+
},
17+
text: {
18+
type: [String, Array],
19+
required: true,
20+
validator: value => {
21+
var result = value != undefined && value != null && value.length > 0;
22+
if (result && Array.isArray(value)) {
23+
value.forEach((v) => {
24+
if(typeof v != 'string')
25+
{
26+
result = false;
27+
}
28+
});
29+
}
30+
return result;
31+
}
32+
},
33+
tag: {
34+
type: String,
35+
default: 'span',
36+
validator: value => ['p', 'h1', 'h2', 'h3', 'h4', 'span'].includes(value)
37+
}
38+
},
39+
data(): VueType {
40+
return {
41+
isDone: false,
42+
arrayIndex: 0,
43+
bindingText: ''
44+
};
45+
},
46+
methods: {
47+
async writeInit() {
48+
if (typeof this.text === "string") {
49+
await this.writeText(this.text);
50+
await this.delay(this.timeTakes);
51+
this.isDone = true;
52+
} else {
53+
if (Array.isArray(this.text)) {
54+
this.setIntervalImmediately(
55+
async () => await this.managerArray(),
56+
this.timeTakes * 1.4 * 2
57+
);
58+
}
59+
}
60+
},
61+
async writeText(text: string) {
62+
let index = 0;
63+
this.bindingText = '';
64+
const period = this.timeTakes / text.length;
65+
const timer = setInterval(() => {
66+
if (index >= text.length - 1) {
67+
clearInterval(timer);
68+
}
69+
index = this.appendText(text[index], index);
70+
}, period);
71+
},
72+
appendText(char: string, index: number) {
73+
this.bindingText += char;
74+
index++;
75+
return index;
76+
},
77+
async eraseText(text: string) {
78+
let index = text.length;
79+
this.bindingText = text;
80+
const period = this.timeTakes / text.length;
81+
const timer = setInterval(() => {
82+
if (index <= 0) {
83+
clearInterval(timer);
84+
}
85+
index = this.removeText(index);
86+
}, period);
87+
},
88+
removeText(index: number) {
89+
this.bindingText = this.bindingText.substring(0, index);
90+
index--;
91+
return index;
92+
},
93+
async managerArray() {
94+
const text = this.text as string[];
95+
await this.writeText(text[this.arrayIndex]);
96+
await this.delay(this.timeTakes * 1.5);
97+
await this.eraseText(text[this.arrayIndex]);
98+
if (this.arrayIndex >= this.text.length - 1) {
99+
this.arrayIndex = 0;
100+
} else {
101+
this.arrayIndex++;
102+
}
103+
return;
104+
},
105+
delay(ms: number) {
106+
return new Promise(resolve => setTimeout(resolve, ms));
107+
},
108+
setIntervalImmediately(func: () => void, interval: number) {
109+
func();
110+
return setInterval(func, interval);
111+
}
112+
},
113+
async mounted() {
114+
await this.writeInit();
115+
},
116+
});

src/vue-typed.vue

+2-154
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,9 @@
1-
<script lang="ts">
2-
import Vue from 'vue';
3-
4-
interface VueType {
5-
isDone: boolean;
6-
arrayIndex: number;
7-
bindingText: string;
8-
}
9-
10-
export default Vue.extend({
11-
name: 'VueTyped', // vue component name
12-
props: {
13-
timeTakes: {
14-
type: Number,
15-
validator: value => value >= 0.0,
16-
default: 2000
17-
},
18-
text: {
19-
type: [String, Array],
20-
required: true,
21-
validator: value => {
22-
var result = value != undefined && value != null && value.length > 0;
23-
if (result && Array.isArray(value)) {
24-
value.forEach((v) => {
25-
if(typeof v != 'string')
26-
{
27-
result = false;
28-
}
29-
});
30-
}
31-
return result;
32-
}
33-
},
34-
tag: {
35-
type: String,
36-
default: 'span',
37-
validator: value => ['p', 'h1', 'h2', 'h3', 'h4', 'span'].includes(value)
38-
}
39-
},
40-
data(): VueType {
41-
return {
42-
isDone: false,
43-
arrayIndex: 0,
44-
bindingText: ''
45-
};
46-
},
47-
methods: {
48-
async writeInit() {
49-
if (typeof this.text === "string") {
50-
await this.writeText(this.text);
51-
await this.delay(this.timeTakes);
52-
this.isDone = true;
53-
} else {
54-
if (Array.isArray(this.text)) {
55-
this.setIntervalImmediately(
56-
async () => await this.managerArray(),
57-
this.timeTakes * 1.4 * 2
58-
);
59-
}
60-
}
61-
},
62-
async writeText(text: string) {
63-
let index = 0;
64-
this.bindingText = '';
65-
const period = this.timeTakes / text.length;
66-
const timer = setInterval(() => {
67-
if (index >= text.length - 1) {
68-
clearInterval(timer);
69-
}
70-
index = this.appendText(text[index], index);
71-
}, period);
72-
},
73-
appendText(char: string, index: number) {
74-
this.bindingText += char;
75-
index++;
76-
return index;
77-
},
78-
async eraseText(text: string) {
79-
let index = text.length;
80-
this.bindingText = text;
81-
const period = this.timeTakes / text.length;
82-
const timer = setInterval(() => {
83-
if (index <= 0) {
84-
clearInterval(timer);
85-
}
86-
index = this.removeText(index);
87-
}, period);
88-
},
89-
removeText(index: number) {
90-
this.bindingText = this.bindingText.substring(0, index);
91-
index--;
92-
return index;
93-
},
94-
async managerArray() {
95-
const text = this.text as string[];
96-
await this.writeText(text[this.arrayIndex]);
97-
await this.delay(this.timeTakes * 1.5);
98-
await this.eraseText(text[this.arrayIndex]);
99-
if (this.arrayIndex >= this.text.length - 1) {
100-
this.arrayIndex = 0;
101-
} else {
102-
this.arrayIndex++;
103-
}
104-
return;
105-
},
106-
delay(ms: number) {
107-
return new Promise(resolve => setTimeout(resolve, ms));
108-
},
109-
setIntervalImmediately(func: () => void, interval: number) {
110-
func();
111-
return setInterval(func, interval);
112-
}
113-
},
114-
async mounted() {
115-
await this.writeInit();
116-
},
117-
});
118-
</script>
119-
1201
<template>
1212
<component :is="tag">
1223
<span class="vue-typed">{{ bindingText }}</span>
1234
<span class="caret" v-if="!isDone"></span>
1245
</component>
1256
</template>
1267

127-
<style scoped>
128-
.caret {
129-
display: inline-block;
130-
vertical-align: baseline;
131-
width: 1px;
132-
background: black;
133-
margin-left: 3px;
134-
position: relative;
135-
top: 2px;
136-
-webkit-animation: caret-animation 0.5s linear infinite;
137-
animation: caret-animation 0.5s linear infinite;
138-
}
139-
140-
.caret:empty:before {
141-
content: "\200b"; /* unicode zero width space character */
142-
}
143-
144-
@keyframes caret-animation {
145-
0% {
146-
opacity: 1;
147-
}
148-
30% {
149-
opacity: 1;
150-
}
151-
40% {
152-
opacity: 0;
153-
}
154-
90% {
155-
opacity: 0;
156-
}
157-
100% {
158-
opacity: 1;
159-
}
160-
}
161-
</style>
8+
<script lang="ts" src="./vue-typed.ts"></script>
9+
<style src="./vue-typed.css" scoped></style>

0 commit comments

Comments
 (0)