├── CHANGELOG.md ├── .gitignore ├── docs ├── .vitepress │ ├── theme │ │ ├── index.js │ │ └── custom.css │ └── config.js ├── vite.config.js ├── public │ └── logo.svg ├── index.en-US.md └── index.zh-CN.md ├── src ├── shim.d.ts ├── index.ts ├── basic │ ├── demo.vue │ ├── index.en-US.md │ └── index.zh-CN.md ├── composition │ ├── demo.vue │ ├── index.en-US.md │ └── index.zh-CN.md ├── VTypical.ts └── typing.ts ├── .prettierrc ├── jest.config.js ├── scripts └── jest.js ├── .eslintrc.js ├── vite.config.js ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .temp 3 | yarn-error.log 4 | dist/ 5 | yarn.lock 6 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/index.js: -------------------------------------------------------------------------------- 1 | import DefaultTheme from 'vitepress/theme'; 2 | import './custom.css'; 3 | 4 | export default DefaultTheme; 5 | -------------------------------------------------------------------------------- /src/shim.d.ts: -------------------------------------------------------------------------------- 1 | // declare module '*.vue' { 2 | // import { ComponentOptions } from 'vue'; 3 | // const comp: ComponentOptions; 4 | // export default comp; 5 | // } 6 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import VTypical from './VTypical.ts'; 2 | 3 | export default VTypical; 4 | 5 | export { VTypical }; 6 | 7 | // export { default as Typical } from './typical/typical.vue'; 8 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 80, 5 | "overrides": [ 6 | { 7 | "files": ".prettierrc", 8 | "options": { "parser": "json" } 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /docs/vite.config.js: -------------------------------------------------------------------------------- 1 | // yarn dev 用到的vite配置 2 | 3 | /** 4 | * @type {import('vite').UserConfig} 5 | */ 6 | import vueJsx from '@vitejs/plugin-vue-jsx'; 7 | import { defineConfig } from 'vite'; 8 | 9 | export default defineConfig({ 10 | plugins: [vueJsx()], 11 | }); 12 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | collectCoverageFrom: ['src/**/*.ts'], 4 | moduleNameMapper: {}, 5 | transform: { 6 | '^.+\\.vue$': 'vue-jest', 7 | }, 8 | moduleFileExtensions: ['vue', 'js', 'json', 'jsx', 'ts', 'tsx', 'node'], 9 | }; 10 | -------------------------------------------------------------------------------- /scripts/jest.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-var-requires */ 2 | /** 3 | * This file is the entry for debug single test file in vscode 4 | * 5 | * Not using node_modules/.bin/jest due to cross platform issues, see 6 | * https://github.com/microsoft/vscode-recipes/issues/107 7 | */ 8 | require('jest').run(process.argv); 9 | -------------------------------------------------------------------------------- /docs/.vitepress/theme/custom.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --c-brand: #10b981; 3 | --c-brand-light: #34d399; 4 | } 5 | 6 | h2 { 7 | border-bottom: none; 8 | } 9 | 10 | .logo { 11 | height: 2.3rem !important; 12 | transform: rotate(90deg); 13 | } 14 | 15 | .nav-bar { 16 | border-bottom: none !important; 17 | box-shadow: 0 8px 24px -2px rgb(0 0 0 / 5%); 18 | } 19 | 20 | .sidebar{ 21 | width: 16rem !important; 22 | } 23 | -------------------------------------------------------------------------------- /src/basic/demo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | 20 | 32 | -------------------------------------------------------------------------------- /src/composition/demo.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | 20 | 32 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | jest: true, 6 | node: true, 7 | }, 8 | extends: [ 9 | 'plugin:vue/essential', 10 | 'eslint:recommended', 11 | '@vue/prettier', 12 | '@vue/typescript/recommended', 13 | '@vue/prettier/@typescript-eslint', 14 | ], 15 | parserOptions: { 16 | ecmaVersion: 2020, 17 | }, 18 | rules: { 19 | '@typescript-eslint/explicit-module-boundary-types': 'off', 20 | }, 21 | overrides: [ 22 | { 23 | files: ['**/__tests__/*.{j,t}s?(x)', '**/dist/**', 'docs/*'], 24 | env: { 25 | jest: true, 26 | }, 27 | }, 28 | ], 29 | }; 30 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | // yarn build 用到的vite配置 2 | 3 | import vue from '@vitejs/plugin-vue'; 4 | import vueJsx from '@vitejs/plugin-vue-jsx'; 5 | import { resolve } from 'path'; 6 | 7 | /** 8 | * @type {import('vite').UserConfig} 9 | */ 10 | export default { 11 | optimizeDeps: { 12 | include: [], 13 | exclude: [], 14 | }, 15 | plugins: [vue(), vueJsx()], 16 | build: { 17 | minify: true, 18 | lib: { 19 | entry: resolve('./src/index.ts'), 20 | name: 'vue-typical', 21 | }, 22 | rollupOptions: { 23 | // make sure to externalize deps that shouldn't be bundled 24 | // into your library 25 | external: ['vue'], 26 | output: { 27 | // Provide global variables to use in the UMD build 28 | // for externalized deps 29 | globals: { 30 | vue: 'Vue', 31 | }, 32 | }, 33 | }, 34 | }, 35 | }; 36 | -------------------------------------------------------------------------------- /src/basic/index.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | map: 3 | path: /basic 4 | --- 5 | 6 | # Basic Usage 7 | 8 | There are some cases of `vue-typical` for you. 9 | 10 | ## Example 11 | 12 | Make a "Hello World" animation with `` 13 | 14 | 18 | 19 | 20 | ## Properties 21 | 22 | | Prop | Required | Type | Eg. | 23 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 24 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 25 | | `loop` | False | Number | `1` or `'Infinity'` | 26 | | `wrapper` | False | String | `'div'` | 27 | -------------------------------------------------------------------------------- /src/basic/index.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | map: 3 | path: /basic 4 | --- 5 | 6 | # Basic Usage 7 | 8 | There are some cases of `vue-typical` for you. 9 | 10 | ## Example 11 | 12 | Make a "Hello World" animation with `` 13 | 14 | 18 | 19 | 20 | ## Properties 21 | 22 | | Prop | Required | Type | Eg. | 23 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 24 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 25 | | `loop` | False | Number | `1` or `'Infinity'` | 26 | | `wrapper` | False | String | `'div'` | 27 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "outDir": "dist", 5 | "sourceMap": false, 6 | "target": "es6", 7 | "module": "esnext", 8 | "moduleResolution": "node", 9 | "allowJs": false, 10 | "noUnusedLocals": true, 11 | "strictNullChecks": true, 12 | "noImplicitAny": true, 13 | "noImplicitThis": true, 14 | "experimentalDecorators": true, 15 | "resolveJsonModule": true, 16 | "esModuleInterop": true, 17 | "removeComments": false, 18 | "declaration": true, 19 | "isolatedModules": true, 20 | "declarationDir": "dist", 21 | "skipLibCheck": true, 22 | "jsx": "preserve", 23 | "lib": ["esnext", "dom"], 24 | "types": ["jest", "node"], 25 | "rootDir": ".", 26 | "paths": { 27 | "@/*": ["src/*"], 28 | "vue-typical": ["src/"] 29 | } 30 | }, 31 | "include": ["src"], 32 | "exclude": ["node_modules", "dist"] 33 | } 34 | -------------------------------------------------------------------------------- /src/composition/index.en-US.md: -------------------------------------------------------------------------------- 1 | --- 2 | map: 3 | path: /composition 4 | --- 5 | 6 | # Composition API 7 | 8 | There are some cases of `vue-typical` for you. 9 | 10 | ## Example 11 | 12 | Make a "Hello World" animation with `` 13 | 14 | 18 | 19 | 20 | ## Properties 21 | 22 | | Prop | Required | Type | Eg. | 23 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 24 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 25 | | `loop` | False | Number | `1` or `'Infinity'` | 26 | | `wrapper` | False | String | `'div'` | 27 | -------------------------------------------------------------------------------- /src/composition/index.zh-CN.md: -------------------------------------------------------------------------------- 1 | --- 2 | map: 3 | path: /composition 4 | --- 5 | 6 | # Composition API 7 | 8 | There are some cases of `vue-typical` for you. 9 | 10 | ## Example 11 | 12 | Make a "Hello World" animation with `` 13 | 14 | 18 | 19 | 20 | ## Properties 21 | 22 | | Prop | Required | Type | Eg. | 23 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 24 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 25 | | `loop` | False | Number | `1` or `'Infinity'` | 26 | | `wrapper` | False | String | `'div'` | 27 | -------------------------------------------------------------------------------- /src/VTypical.ts: -------------------------------------------------------------------------------- 1 | import { h, onMounted, ref, defineComponent } from 'vue'; 2 | import typing from './typing'; 3 | 4 | const loopedTyping = typing; 5 | 6 | export default defineComponent({ 7 | name: 'Typical', 8 | props: { 9 | steps: { 10 | type: Array, 11 | required: true, 12 | }, 13 | wrapper: { 14 | type: String, 15 | default: 'div', 16 | }, 17 | loop: { 18 | type: Number, 19 | default: 1, 20 | }, 21 | }, 22 | render() { 23 | return h(this.wrapper, { 24 | ref: 'myRef', 25 | }); 26 | }, 27 | setup: ({ steps, loop }) => { 28 | const myRef = ref(null); 29 | 30 | onMounted(() => { 31 | const dom = myRef.value; 32 | if (loop === Infinity) { 33 | typing(dom, ...steps, loopedTyping); 34 | } else if (typeof loop === 'number' && loop > 0) { 35 | typing(dom, ...Array(loop).fill(steps).flat()); 36 | } else { 37 | typing(dom, ...steps); 38 | } 39 | }); 40 | 41 | return { 42 | myRef, 43 | }; 44 | }, 45 | }); 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-present Turkyden 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/public/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/typing.ts: -------------------------------------------------------------------------------- 1 | export default async function typing(node, ...args) { 2 | for (const arg of args) { 3 | switch (typeof arg) { 4 | case 'string': 5 | await edit(node, arg); 6 | break; 7 | case 'number': 8 | await wait(arg); 9 | break; 10 | case 'function': 11 | await arg(node, ...args); 12 | break; 13 | default: 14 | await arg; 15 | } 16 | } 17 | } 18 | 19 | async function edit(node, text) { 20 | const overlap = getOverlap(node.textContent, text); 21 | await perform(node, [ 22 | ...deleter(node.textContent, overlap), 23 | ...writer(text, overlap), 24 | ]); 25 | } 26 | 27 | async function wait(ms) { 28 | await new Promise((resolve) => setTimeout(resolve, ms)); 29 | } 30 | 31 | async function perform(node, edits, speed = 60) { 32 | for (const op of editor(edits)) { 33 | op(node); 34 | await wait(speed + speed * (Math.random() - 0.5)); 35 | } 36 | } 37 | 38 | export function* editor(edits) { 39 | for (const edit of edits) { 40 | yield (node) => requestAnimationFrame(() => (node.textContent = edit)); 41 | } 42 | } 43 | 44 | export function* writer([...text], startIndex = 0, endIndex = text.length) { 45 | while (startIndex < endIndex) { 46 | yield text.slice(0, ++startIndex).join(''); 47 | } 48 | } 49 | 50 | export function* deleter([...text], startIndex = 0, endIndex = text.length) { 51 | while (endIndex > startIndex) { 52 | yield text.slice(0, --endIndex).join(''); 53 | } 54 | } 55 | 56 | export function getOverlap(start, [...end]) { 57 | return [...start, NaN].findIndex((char, i) => end[i] !== char); 58 | } 59 | -------------------------------------------------------------------------------- /docs/.vitepress/config.js: -------------------------------------------------------------------------------- 1 | const base = process.env.NODE_ENV === 'production' ? '/' : ''; 2 | const { resolve } = require('path'); 3 | 4 | module.exports = { 5 | title: 'Vue Typical', 6 | description: '', 7 | // 扫描srcIncludes里面的 *.md文件 8 | srcIncludes: ['src'], 9 | alias: { 10 | // 为了能在demo中正确的使用 import { X } from 'vue-typical' 11 | [`vue-typical`]: resolve('./src'), 12 | }, 13 | base, 14 | themeConfig: { 15 | logo: '/logo.svg', 16 | locales: { 17 | '/': { 18 | lang: 'en-US', 19 | title: 'VueTypical', 20 | description: '', 21 | label: 'English', 22 | selectText: 'Languages', 23 | nav: [ 24 | { text: 'Guide', link: '/' }, 25 | { 26 | text: 'Changelog', 27 | link: 28 | 'https://github.com/Turkyden/vue-typical/blob/master/CHANGELOG.md', 29 | }, 30 | ], 31 | sidebar: [ 32 | { text: 'Getting Started', link: '/' }, 33 | { 34 | text: 'Demo', 35 | children: [ 36 | { text: 'Basic Usage', link: '/basic/' }, 37 | { text: 'Composition API', link: '/composition/' }, 38 | ], 39 | }, 40 | ], 41 | }, 42 | '/zh/': { 43 | lang: 'zh-CN', 44 | title: 'VueTypical', 45 | description: '', 46 | label: '中文', 47 | selectText: '语言', 48 | nav: [ 49 | { text: '入门指南', link: '/zh/' }, 50 | { 51 | text: '更新日志', 52 | link: 53 | 'https://github.com/Turkyden/vue-typical/blob/master/CHANGELOG.md', 54 | }, 55 | ], 56 | sidebar: [ 57 | { text: '快速开始', link: '/zh/' }, 58 | { 59 | text: '示例', 60 | children: [ 61 | { text: '基本方法', link: '/zh/basic/' }, 62 | { text: 'Composition API', link: '/zh/composition/' }, 63 | ], 64 | }, 65 | ], 66 | }, 67 | }, 68 | search: { 69 | searchMaxSuggestions: 10, 70 | }, 71 | repo: 'Turkyden/vue-typical', 72 | repoLabel: 'Github', 73 | lastUpdated: true, 74 | prevLink: true, 75 | nextLink: true, 76 | }, 77 | }; 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-typical", 3 | "version": "2.1.0", 4 | "description": "Vue Animated typing in ~400 bytes 🐡 of JavaScript.", 5 | "keywords": [ 6 | "vue", 7 | "vue-component", 8 | "typical", 9 | "typing", 10 | "animation", 11 | "vue3", 12 | "components" 13 | ], 14 | "authors": { 15 | "name": "Turkyden", 16 | "email": "wj871287@gmail.com" 17 | }, 18 | "homepage": "http://github.com/Turkyden/vue-typical", 19 | "repository": { 20 | "type": "git", 21 | "url": "git@github.com:Turkyden/vue-typical.git" 22 | }, 23 | "bugs": { 24 | "url": "http://github.com/Turkyden/vue-typical/issues" 25 | }, 26 | "license": "MIT", 27 | "main": "dist/vue-typical.umd.js", 28 | "module": "dist/vue-typical.es.js", 29 | "files": [ 30 | "dist", 31 | "package.json", 32 | "README.md", 33 | "LICENSE" 34 | ], 35 | "types": "dist/src/index.d.ts", 36 | "scripts": { 37 | "start": "vitepress-fc dev --root=docs --host", 38 | "build": "vite build && yarn type", 39 | "type": "tsc -d", 40 | "test": "jest", 41 | "docs:build": "rimraf docs/dist && cross-env NODE_ENV=production vitepress-fc build --root=docs", 42 | "docs:serve": "cross-env NODE_ENV=production vitepress-fc serve --root=docs", 43 | "docs:build-serve": "cross-env NODE_ENV=true yarn docs:build && yarn docs:serve", 44 | "docs:deploy": "gh-pages -d docs/dist -t true", 45 | "docs:build-deploy": "yarn docs:build && yarn docs:deploy", 46 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s", 47 | "lint": "eslint src/**/*.{vue,js,ts,tsx}", 48 | "lint:fix": "yarn lint -- --fix" 49 | }, 50 | "devDependencies": { 51 | "@rollup/plugin-node-resolve": "^10.0.0", 52 | "@types/jest": "^26.0.15", 53 | "@typescript-eslint/eslint-plugin": "^4.8.1", 54 | "@typescript-eslint/parser": "^4.8.1", 55 | "@vitejs/plugin-vue": "^1.1.4", 56 | "@vitejs/plugin-vue-jsx": "^1.1.7", 57 | "@vue/eslint-config-prettier": "^6.0.0", 58 | "@vue/eslint-config-typescript": "^7.0.0", 59 | "@vue/test-utils": "^2.0.0-beta.10", 60 | "@vuedx/typescript-plugin-vue": "^0.6.3", 61 | "babel-jest": "^26.6.3", 62 | "conventional-changelog-cli": "^2.1.1", 63 | "cross-env": "^7.0.2", 64 | "eslint": "^7.13.0", 65 | "eslint-plugin-prettier": "^3.1.4", 66 | "eslint-plugin-vue": "^7.1.0", 67 | "gh-pages": "^3.1.0", 68 | "husky": "^4.3.0", 69 | "jest": "^26.6.3", 70 | "np": "^7.4.0", 71 | "prettier": "^2.1.2", 72 | "pretty-quick": "^3.1.0", 73 | "rimraf": "^3.0.2", 74 | "rollup-plugin-alias": "^2.2.0", 75 | "rollup-plugin-commonjs": "^10.1.0", 76 | "rollup-plugin-css-only": "^2.1.0", 77 | "rollup-plugin-typescript2": "^0.30.0", 78 | "rollup-plugin-vue": "^6.0.0-beta.11", 79 | "ts-jest": "^26.4.4", 80 | "typescript": "^4.2.2", 81 | "vite": "^2.4.1", 82 | "vitepress-for-component": "latest", 83 | "vue-jest": "^5.0.0-alpha.6" 84 | }, 85 | "publishConfig": { 86 | "access": "public", 87 | "registry": "https://registry.npmjs.org" 88 | }, 89 | "husky": { 90 | "hooks": { 91 | "pre-commit": "pretty-quick --staged" 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /docs/index.en-US.md: -------------------------------------------------------------------------------- 1 | English | [简体中文](https://vue-typical.vercel.app/zh/) 2 | 3 |

Vue Typical

4 | 5 |

Vue Animated typing in ~400 bytes 🐡 of JavaScript. Preview →

6 | 7 |

8 | npm npm license vitepress jsdelivr 9 |

10 | 11 | 16 | 17 |

Live Demo ✨ https://vue-typical.vercel.app

18 | 19 | ## 📦 Installation 20 | 21 | Install with yarn 22 | 23 | ```bash 24 | yarn add vue-typical 25 | ``` 26 | 27 | Or you can 28 | 29 | ```bash 30 | npm install vue-typical 31 | ``` 32 | 33 | Or inject the script at your page by [jsdelivr CDN](https://www.jsdelivr.com/) 34 | 35 | ```html 36 | 37 | ``` 38 | 39 | ## 🚀 Usage 40 | 41 | ### 1. Component 42 | 43 | You can import it as a custom component. 44 | 45 | ```vue | pure 46 | 54 | 55 | 64 | ``` 65 | 66 | ### 2. Plugin API 67 | 68 | If you want to configure default options, you can register this plugin through the use API of Vue.js. 69 | 70 | ```tsx | pure 71 | // main.js or index.js 72 | import VTypical from 'vue-typical'; 73 | 74 | Vue.use(VTypical, { 75 | /* options */ 76 | }); 77 | ``` 78 | 79 | If you use the plugin API, the `VTypical` component will be registered as a global component just like when including it with the `script` tag, but you won't need to re-register it through the `components` property in your own components. 80 | 81 | ### 3. Composition API 82 | 83 | You can also create typical animation by the composition API `useTypical`. 84 | 85 | ```typescript | pure 86 | const ref = useTypical(options); 87 | ``` 88 | 89 | Coming Soon ... 90 | 91 | ## 📑 Properties 92 | 93 | | Prop | Required | Type | Eg. | 94 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 95 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 96 | | `loop` | False | Number | `1` or `'Infinity'` | 97 | | `wrapper` | False | String | `'div'` | 98 | 99 | ## ✨ Style 100 | 101 | Add the blink cursor effect with `blink` classname. 102 | 103 | ```css 104 | .blink::after { 105 | content: '|'; 106 | animation: blink 1s infinite step-start; 107 | } 108 | 109 | @keyframes blink { 110 | 50% { 111 | opacity: 0; 112 | } 113 | } 114 | ``` 115 | 116 | ## 🔢 Coming Soon 117 | 118 | - [ ] The demo of composition API in Vue 3.0 119 | 120 | ## 🔨 Contribute 121 | 122 | Install dependencies, 123 | 124 | ```bash 125 | $ npm i 126 | ``` 127 | 128 | Start the dev server, 129 | 130 | ```bash 131 | $ npm start 132 | ``` 133 | 134 | Build documentation, 135 | 136 | ```bash 137 | $ npm run docs:build 138 | ``` 139 | 140 | Build library via `father-build`, 141 | 142 | ```bash 143 | $ npm run build 144 | ``` 145 | 146 | ## ❤️ Contributors 147 | 148 | Thanks goes to these people: 149 | 150 | ![Contributors](https://contrib.rocks/image?repo=Turkyden/vue-typical) 151 | 152 | Please Feel free to enjoy and participate in open source! 153 | 154 | ## ⭐ Stargazers 155 | 156 | Thanks for your star! 157 | 158 | [![Stargazers repo roster for @Turkyden/vue-typical](https://reporoster.com/stars/Turkyden/vue-typical)](https://github.com/Turkyden/vue-typical/stargazers) 159 | 160 | ## 🔖 License 161 | 162 | This library is based on [@camwiegert/typical](https://github.com/camwiegert/typical) work and it currently is just a wrapper for vue. 163 | 164 | Inspired by [@catalinmiron/react-typical](https://github.com/catalinmiron/react-typical). 165 | 166 | [MIT](https://github.com/Turkyden/vue-typical/blob/main/LICENSE) © [Turkyden](https://github.com/Turkyden) 167 | -------------------------------------------------------------------------------- /docs/index.zh-CN.md: -------------------------------------------------------------------------------- 1 | English | [简体中文](https://vue-typical.vercel.app/zh/) 2 | 3 |

Vue Typical

4 | 5 |

Vue Animated typing in ~400 bytes 🐡 of JavaScript. Preview →

6 | 7 |

8 | npm npm license vitepress jsdelivr 9 |

10 | 11 | 16 | 17 |

Live Demo ✨ https://vue-typical.vercel.app

18 | 19 | ## 📦 Installation 20 | 21 | Install with yarn 22 | 23 | ```bash 24 | yarn add vue-typical 25 | ``` 26 | 27 | Or you can 28 | 29 | ```bash 30 | npm install vue-typical 31 | ``` 32 | 33 | Or inject the script at your page by [jsdelivr CDN](https://www.jsdelivr.com/) 34 | 35 | ```html 36 | 37 | ``` 38 | 39 | ## 🚀 Usage 40 | 41 | ### 1. Component 42 | 43 | You can import it as a custom component. 44 | 45 | ```vue | pure 46 | 54 | 55 | 64 | ``` 65 | 66 | ### 2. Plugin API 67 | 68 | If you want to configure default options, you can register this plugin through the use API of Vue.js. 69 | 70 | ```tsx | pure 71 | // main.js or index.js 72 | import VTypical from 'vue-typical'; 73 | 74 | Vue.use(VTypical, { 75 | /* options */ 76 | }); 77 | ``` 78 | 79 | If you use the plugin API, the `VTypical` component will be registered as a global component just like when including it with the `script` tag, but you won't need to re-register it through the `components` property in your own components. 80 | 81 | ### 3. Composition API 82 | 83 | You can also create typical animation by the composition API `useTypical`. 84 | 85 | ```typescript | pure 86 | const ref = useTypical(options); 87 | ``` 88 | 89 | Coming Soon ... 90 | 91 | ## 📑 Properties 92 | 93 | | Prop | Required | Type | Eg. | 94 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 95 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 96 | | `loop` | False | Number | `1` or `'Infinity'` | 97 | | `wrapper` | False | String | `'div'` | 98 | 99 | ## ✨ Style 100 | 101 | Add the blink cursor effect with `blink` classname. 102 | 103 | ```css 104 | .blink::after { 105 | content: '|'; 106 | animation: blink 1s infinite step-start; 107 | } 108 | 109 | @keyframes blink { 110 | 50% { 111 | opacity: 0; 112 | } 113 | } 114 | ``` 115 | 116 | ## 🔢 Coming Soon 117 | 118 | - [ ] The demo of composition API in Vue 3.0 119 | 120 | ## 🔨 Contribute 121 | 122 | Install dependencies, 123 | 124 | ```bash 125 | $ npm i 126 | ``` 127 | 128 | Start the dev server, 129 | 130 | ```bash 131 | $ npm start 132 | ``` 133 | 134 | Build documentation, 135 | 136 | ```bash 137 | $ npm run docs:build 138 | ``` 139 | 140 | Build library via `father-build`, 141 | 142 | ```bash 143 | $ npm run build 144 | ``` 145 | 146 | ## ❤️ Contributors 147 | 148 | Thanks goes to these people: 149 | 150 | ![Contributors](https://contrib.rocks/image?repo=Turkyden/vue-typical) 151 | 152 | Please Feel free to enjoy and participate in open source! 153 | 154 | ## ⭐ Stargazers 155 | 156 | Thanks for your star! 157 | 158 | [![Stargazers repo roster for @Turkyden/vue-typical](https://reporoster.com/stars/Turkyden/vue-typical)](https://github.com/Turkyden/vue-typical/stargazers) 159 | 160 | ## 🔖 License 161 | 162 | This library is based on [@camwiegert/typical](https://github.com/camwiegert/typical) work and it currently is just a wrapper for vue. 163 | 164 | Inspired by [@catalinmiron/react-typical](https://github.com/catalinmiron/react-typical). 165 | 166 | [MIT](https://github.com/Turkyden/vue-typical/blob/main/LICENSE) © [Turkyden](https://github.com/Turkyden) 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | English | [简体中文](https://vue-typical.vercel.app/zh/) 2 | 3 |

Vue Typical

4 | 5 |

Vue Animated typing in ~400 bytes 🐡 of JavaScript. Preview →

6 | 7 |

8 | npm npm license vitepress jsdelivr 9 |

10 | 11 | 16 | 17 |

Live Demo ✨ https://vue-typical.vercel.app

18 | 19 | ## 📦 Installation 20 | 21 | Install with yarn 22 | 23 | ```bash 24 | yarn add vue-typical 25 | ``` 26 | 27 | Or you can 28 | 29 | ```bash 30 | npm install vue-typical 31 | ``` 32 | 33 | Or inject the script at your page by [jsdelivr CDN](https://www.jsdelivr.com/) 34 | 35 | ```html 36 | 37 | ``` 38 | 39 | > 💡 This library Just support Vue 3 now 40 | 41 | If you are Vue 2, please see the [branch v1](https://github.com/Turkyden/vue-typical/tree/v1) and install [vue-typical@1.6.2](https://github.com/Turkyden/vue-typical/tree/v1) 42 | 43 | ## 🚀 Usage 44 | 45 | ### 1. Component 46 | 47 | You can import it as a custom component. 48 | 49 | ```vue | pure 50 | 58 | 59 | 68 | ``` 69 | 70 | ### 2. Plugin API 71 | 72 | If you want to configure default options, you can register this plugin through the use API of Vue.js. 73 | 74 | ```tsx | pure 75 | // main.js or index.js 76 | import VTypical from 'vue-typical'; 77 | 78 | Vue.use(VTypical, { 79 | /* options */ 80 | }); 81 | ``` 82 | 83 | If you use the plugin API, the `VTypical` component will be registered as a global component just like when including it with the `script` tag, but you won't need to re-register it through the `components` property in your own components. 84 | 85 | ### 3. Composition API 86 | 87 | You can also create typical animation by the composition API `useTypical`. 88 | 89 | ```typescript | pure 90 | const ref = useTypical(options); 91 | ``` 92 | 93 | Coming Soon ... 94 | 95 | ## 📑 Properties 96 | 97 | | Prop | Required | Type | Eg. | 98 | | --------- | -------- | ----------------------------------- | -------------------------------------- | 99 | | `steps` | True | Array | `['Hello', 1000, () => alert('Word')]` | 100 | | `loop` | False | Number | `1` or `'Infinity'` | 101 | | `wrapper` | False | String | `'div'` | 102 | 103 | ## ✨ Style 104 | 105 | Add the blink cursor effect with `blink` classname. 106 | 107 | ```css 108 | .blink::after { 109 | content: '|'; 110 | animation: blink 1s infinite step-start; 111 | } 112 | 113 | @keyframes blink { 114 | 50% { 115 | opacity: 0; 116 | } 117 | } 118 | ``` 119 | 120 | ## 🔢 Coming Soon 121 | 122 | - [ ] The demo of composition API in Vue 3.0 123 | - [ ] Supported Vue 2 & 3 124 | 125 | ## 🔨 Contribute 126 | 127 | Install dependencies, 128 | 129 | ```bash 130 | $ npm i 131 | ``` 132 | 133 | Start the dev server, 134 | 135 | ```bash 136 | $ npm start 137 | ``` 138 | 139 | Build documentation, 140 | 141 | ```bash 142 | $ npm run docs:build 143 | ``` 144 | 145 | Build library via `father-build`, 146 | 147 | ```bash 148 | $ npm run build 149 | ``` 150 | 151 | ## ❤️ Contributors 152 | 153 | Thanks goes to these people: 154 | 155 | ![Contributors](https://contrib.rocks/image?repo=Turkyden/vue-typical) 156 | 157 | Please Feel free to enjoy and participate in open source! 158 | 159 | ## ⭐ Stargazers 160 | 161 | Thanks for your star! 162 | 163 | [![Stargazers repo roster for @Turkyden/vue-typical](https://reporoster.com/stars/Turkyden/vue-typical)](https://github.com/Turkyden/vue-typical/stargazers) 164 | 165 | ## 🔖 License 166 | 167 | This library is based on [@camwiegert/typical](https://github.com/camwiegert/typical) work and it currently is just a wrapper for vue. 168 | 169 | Inspired by [@catalinmiron/react-typical](https://github.com/catalinmiron/react-typical). 170 | 171 | [MIT](https://github.com/Turkyden/vue-typical/blob/main/LICENSE) © [Turkyden](https://github.com/Turkyden) --------------------------------------------------------------------------------