├── dist ├── Typewriter.test.d.ts ├── setupTests.d.ts ├── setupTests.js ├── Typewriter.module.css ├── Typewriter.d.ts ├── Typewriter.js └── Typewriter.test.js ├── src ├── declarations.d.ts ├── setupTests.ts ├── Typewriter.module.css ├── Typewriter.tsx └── Typewriter.test.tsx ├── usage.gif ├── .github ├── dependabot.yml └── workflows │ ├── node.js.yml │ └── codeql-analysis.yml ├── package.json ├── LICENSE ├── .gitignore ├── .npmignore ├── README.md └── tsconfig.json /dist/Typewriter.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /src/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css'; -------------------------------------------------------------------------------- /dist/setupTests.d.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom'; 2 | -------------------------------------------------------------------------------- /usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gerardmarquinarubio/ReactTypewriter/HEAD/usage.gif -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /dist/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /dist/Typewriter.module.css: -------------------------------------------------------------------------------- 1 | .cursor { 2 | animation: blinkingText 1s infinite; 3 | } 4 | 5 | @keyframes blinkingText { 6 | 0% { 7 | opacity: 1; 8 | } 9 | 10 | 49% { 11 | opacity: 1; 12 | } 13 | 14 | 60% { 15 | opacity: 0; 16 | } 17 | 18 | 99% { 19 | opacity: 0; 20 | } 21 | 22 | 100% { 23 | opacity: 1; 24 | } 25 | } -------------------------------------------------------------------------------- /src/Typewriter.module.css: -------------------------------------------------------------------------------- 1 | .cursor { 2 | animation: blinkingText 1s infinite; 3 | } 4 | 5 | @keyframes blinkingText { 6 | 0% { 7 | opacity: 1; 8 | } 9 | 10 | 49% { 11 | opacity: 1; 12 | } 13 | 14 | 60% { 15 | opacity: 0; 16 | } 17 | 18 | 99% { 19 | opacity: 0; 20 | } 21 | 22 | 100% { 23 | opacity: 1; 24 | } 25 | } -------------------------------------------------------------------------------- /dist/Typewriter.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export interface ITypewriterProps { 3 | text: string | string[]; 4 | speed?: number; 5 | loop?: boolean; 6 | random?: number; 7 | delay?: number; 8 | cursor?: boolean; 9 | onFinished?: Function; 10 | onStart?: Function; 11 | } 12 | export default function Typewriter({ text, speed, loop, random, delay, cursor, onFinished, onStart }: ITypewriterProps): JSX.Element; 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [16.x] 20 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 21 | 22 | steps: 23 | - uses: actions/checkout@v3 24 | - name: Use Node.js ${{ matrix.node-version }} 25 | uses: actions/setup-node@v3 26 | with: 27 | node-version: ${{ matrix.node-version }} 28 | - run: npm i --dev 29 | - run: npm run clean 30 | - run: npm run prepublish 31 | - run: npm test 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-ts-typewriter", 3 | "version": "0.1.8b", 4 | "description": "React typewriter component written in TypeScript with React 18", 5 | "main": "dist/Typewriter.js", 6 | "types": "dist/Typewriter.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "git+https://github.com/gerardmarquinarubio/ReactTypewriter.git" 10 | }, 11 | "keywords": [ 12 | "react", 13 | "typescript", 14 | "types", 15 | "components" 16 | ], 17 | "type": "module", 18 | "author": "Gerard Marquina Rubio", 19 | "license": "BSD-3-Clause", 20 | "bugs": { 21 | "url": "https://github.com/gerardmarquinarubio/ReactTypewriter/issues" 22 | }, 23 | "scripts": { 24 | "test": "react-scripts test", 25 | "clean": "rm -rf ./dist/", 26 | "prepublish": "tsc && cp ./src/Typewriter.module.css ./dist/" 27 | }, 28 | "homepage": "https://github.com/gerardmarquinarubio/ReactTypewriter#readme", 29 | "dependencies": { 30 | "react": "^18.2.0", 31 | "react-dom": "^18.2.0" 32 | }, 33 | "devDependencies": { 34 | "@testing-library/jest-dom": "^5.16.4", 35 | "@testing-library/react": "^13.3.0", 36 | "@types/jest": "^29.2.5", 37 | "@types/node": "^18.0.0", 38 | "@types/react": "^18.0.14", 39 | "@types/react-dom": "^18.0.5", 40 | "jest": "^29.0.0", 41 | "react-scripts": "^5.0.1", 42 | "typescript": "^4.7.4" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, Gerard Marquina Rubio 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /dist/Typewriter.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import styles from './Typewriter.module.css'; 3 | const DEFAULT_MS = 30; 4 | export default function Typewriter({ text, speed = DEFAULT_MS, loop = false, random = DEFAULT_MS, delay = DEFAULT_MS, cursor = true, onFinished = () => { }, onStart = () => { } }) { 5 | const [currentStringIndex, setCurrentStringIndex] = useState(0); 6 | const [currentTextIndex, setCurrentTextIndex] = useState(0); 7 | if (!Array.isArray(text)) 8 | text = [text]; 9 | useEffect(() => { 10 | setTimeout(() => { 11 | if (currentTextIndex === 0) 12 | onStart(); 13 | if (currentTextIndex < text[currentStringIndex].length) { 14 | setCurrentTextIndex(currentTextIndex + 1); 15 | } 16 | else { 17 | if (currentStringIndex < text.length - 1) { 18 | setTimeout(() => { 19 | setCurrentTextIndex(0); 20 | setCurrentStringIndex(currentStringIndex + 1); 21 | }, delay); 22 | } 23 | else { 24 | if (loop) { 25 | setTimeout(() => { 26 | setCurrentTextIndex(0); 27 | setCurrentStringIndex(0); 28 | }, delay); 29 | } 30 | else { 31 | onFinished(); 32 | } 33 | } 34 | } 35 | }, speed + (Math.random() * random)); 36 | }); 37 | return (React.createElement("span", null, 38 | text[currentStringIndex].substring(0, currentTextIndex), 39 | React.createElement("span", { className: styles.cursor }, cursor && '▎'))); 40 | } 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | 84 | # Gatsby files 85 | .cache/ 86 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 87 | # https://nextjs.org/blog/next-9-1#public-directory-support 88 | # public 89 | 90 | # vuepress build output 91 | .vuepress/dist 92 | 93 | # Serverless directories 94 | .serverless/ 95 | 96 | # FuseBox cache 97 | .fusebox/ 98 | 99 | # DynamoDB Local files 100 | .dynamodb/ 101 | 102 | # TernJS port file 103 | .tern-port 104 | 105 | package-lock.json 106 | .DS_Store -------------------------------------------------------------------------------- /src/Typewriter.tsx: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | 3 | import styles from './Typewriter.module.css'; 4 | 5 | const DEFAULT_MS = 30; 6 | 7 | export interface ITypewriterProps { 8 | text: string | string[]; 9 | speed?: number; 10 | loop?: boolean; 11 | random?: number; 12 | delay?: number; 13 | cursor?: boolean; 14 | onFinished?: Function; 15 | onStart?: Function; 16 | } 17 | 18 | export default function Typewriter({text, speed = DEFAULT_MS, loop = false, random = DEFAULT_MS, delay = DEFAULT_MS, cursor = true, onFinished = () => {}, onStart = () => {}}: ITypewriterProps) { 19 | 20 | const [currentStringIndex, setCurrentStringIndex] = useState(0); 21 | const [currentTextIndex, setCurrentTextIndex] = useState(0); 22 | 23 | if (!Array.isArray(text)) 24 | text = [text] 25 | 26 | useEffect( () => { 27 | setTimeout( () => { 28 | if (currentTextIndex === 0) 29 | onStart(); 30 | if (currentTextIndex < text[currentStringIndex].length) { 31 | setCurrentTextIndex(currentTextIndex + 1); 32 | } else { 33 | if (currentStringIndex < text.length-1) { 34 | setTimeout( () => { 35 | setCurrentTextIndex(0); 36 | setCurrentStringIndex( currentStringIndex + 1); 37 | }, delay); 38 | } else { 39 | if (loop) { 40 | setTimeout( () => { 41 | setCurrentTextIndex(0); 42 | setCurrentStringIndex(0); 43 | }, delay); 44 | } else { 45 | 46 | onFinished(); 47 | } 48 | } 49 | } 50 | }, speed + (Math.random() * random)); 51 | }); 52 | 53 | return ( 54 | 55 | { 56 | text[currentStringIndex].substring(0, currentTextIndex) 57 | } 58 | 59 | { 60 | cursor && '▎' 61 | } 62 | 63 | 64 | ); 65 | } -------------------------------------------------------------------------------- /src/Typewriter.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import Typewriter from "./Typewriter"; 4 | import { act } from 'react-dom/test-utils'; 5 | 6 | describe('Typewriter', () => { 7 | describe('should render without crashing', () => { 8 | it('using text prop', () => { 9 | render(); 10 | }); 11 | it('using loop prop', () => { 12 | render(); 13 | }); 14 | it('using array prop', () => { 15 | render(); 16 | }); 17 | it('using loop', () => { 18 | render(); 19 | }); 20 | it('using speed', () => { 21 | render(); 22 | }); 23 | it('using delay', () => { 24 | render(); 25 | }); 26 | it('using random', () => { 27 | render(); 28 | }) 29 | it('using cursor', () => { 30 | render(); 31 | }) 32 | }); 33 | 34 | describe('should trigger events', () => { 35 | test('onStart', done => { 36 | render( done()} />); 37 | }); 38 | test('onFinished', done => { 39 | render( done()} />); 40 | }); 41 | }); 42 | describe('should render text properly', () => { 43 | test('single string', done => { 44 | render( { 45 | expect(screen.getByText('Hello!')).toBeInTheDocument(); 46 | done(); 47 | }}/>); 48 | }); 49 | test('array of string', done => { 50 | render( { 51 | expect(screen.getByText('Hello!')).toBeInTheDocument(); 52 | done(); 53 | }}/>); 54 | }); 55 | }); 56 | }); -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | 84 | # Gatsby files 85 | .cache/ 86 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 87 | # https://nextjs.org/blog/next-9-1#public-directory-support 88 | # public 89 | 90 | # vuepress build output 91 | .vuepress/dist 92 | 93 | # Serverless directories 94 | .serverless/ 95 | 96 | # FuseBox cache 97 | .fusebox/ 98 | 99 | # DynamoDB Local files 100 | .dynamodb/ 101 | 102 | # TernJS port file 103 | .tern-port 104 | 105 | test/ 106 | package-lock.json 107 | .DS_Store 108 | 109 | *.gif 110 | *.jpg 111 | *.jpeg 112 | *.png 113 | src/ -------------------------------------------------------------------------------- /dist/Typewriter.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import Typewriter from "./Typewriter"; 4 | describe('Typewriter', () => { 5 | describe('should render without crashing', () => { 6 | it('using text prop', () => { 7 | render(React.createElement(Typewriter, { text: "Hello!" })); 8 | }); 9 | it('using loop prop', () => { 10 | render(React.createElement(Typewriter, { text: "Hello!", loop: true })); 11 | }); 12 | it('using array prop', () => { 13 | render(React.createElement(Typewriter, { text: ["Hello!", "how", "are", "you?"] })); 14 | }); 15 | it('using loop', () => { 16 | render(React.createElement(Typewriter, { text: "Hello!", loop: true })); 17 | }); 18 | it('using speed', () => { 19 | render(React.createElement(Typewriter, { text: "Hello!", speed: 500 })); 20 | }); 21 | it('using delay', () => { 22 | render(React.createElement(Typewriter, { text: "Hello!", delay: 500 })); 23 | }); 24 | it('using random', () => { 25 | render(React.createElement(Typewriter, { text: "Hello!", random: 500 })); 26 | }); 27 | it('using cursor', () => { 28 | render(React.createElement(Typewriter, { text: "Hello!", cursor: false })); 29 | }); 30 | }); 31 | describe('should trigger events', () => { 32 | test('onStart', done => { 33 | render(React.createElement(Typewriter, { text: "Hello!", onStart: () => done() })); 34 | }); 35 | test('onFinished', done => { 36 | render(React.createElement(Typewriter, { text: "Hello!", onFinished: () => done() })); 37 | }); 38 | }); 39 | describe('should render text properly', () => { 40 | test('single string', done => { 41 | render(React.createElement(Typewriter, { text: "Hello!", cursor: false, onFinished: () => { 42 | expect(screen.getByText('Hello!')).toBeInTheDocument(); 43 | done(); 44 | } })); 45 | }); 46 | test('array of string', done => { 47 | render(React.createElement(Typewriter, { text: ["Now!", "Hello!"], cursor: false, onFinished: () => { 48 | expect(screen.getByText('Hello!')).toBeInTheDocument(); 49 | done(); 50 | } })); 51 | }); 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ "main" ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ "main" ] 20 | schedule: 21 | - cron: '41 14 * * 0' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'typescript', 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | 52 | # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs 53 | # queries: security-extended,security-and-quality 54 | 55 | 56 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 57 | # If this step fails, then you should remove it and run the build manually (see below) 58 | - name: Autobuild 59 | uses: github/codeql-action/autobuild@v2 60 | 61 | # ℹ️ Command-line programs to run using the OS shell. 62 | # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun 63 | 64 | # If the Autobuild fails above, remove it and uncomment the following three lines. 65 | # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. 66 | 67 | # - run: | 68 | # echo "Run, Build Application using script" 69 | # ./location_of_script_within_repo/buildscript.sh 70 | 71 | - name: Perform CodeQL Analysis 72 | uses: github/codeql-action/analyze@v2 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

〰 ⌨️ 〰 React Typewriter 〰 ⌨️ 〰

2 |

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | React Typewriter is a simple component that allows you to create a nice "typewriter" effect to any text by simply invoking the component. Try on codesandbox.io. 17 | 18 | ## Installation 19 | 20 | ```sh 21 | npm i react-ts-typewriter 22 | ``` 23 | 24 | ## Example usage 25 | 26 | ```tsx 27 | import Typewriter from 'react-ts-typewriter'; 28 | 29 | export default function myComponent() { 30 | return ( 31 |

32 | 33 |

34 | ) 35 | } 36 | ``` 37 | 38 | ## Props 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |
Prop nameTypeDescriptionRequiredDefault
textstring | string[]Text to display as string or an array of stringstrue
speednumberHow long (in ms) does the the typewriter wait after typing one characterfalse30ms
loopbooleanSet to true if the typewriter should loop after finishing typing the string(s)falsefalse
randomnumberMs of randomness that should be added after each keystroke. If set to zero then each stroke will strictly take speedms to completefalse30ms
delaynumberMs to wait after compleating the word. Useless if loop is set to false or text is not an arrayfalse30ms
cursorbooleanSet to false if the typewriter should not render a blinking cursor character at the end of the stringfalsetrue
onFinishedFunctionCallback function after Typewriter animation is complete, never triggers if loop is truefalse() => void
onStartFunctionCallback function before Typewriter animation is started on each stringfalse() => void
-------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es6", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | "jsx": "react", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "es6", /* Specify what module code is generated. */ 29 | "rootDir": "./src", /* Specify the root folder within your source files. */ 30 | "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "resolveJsonModule": true, /* Enable importing .json files. */ 39 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 40 | 41 | /* JavaScript Support */ 42 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 43 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 44 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 45 | 46 | /* Emit */ 47 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 48 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 49 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 50 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 51 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 52 | "outDir": "./dist", /* Specify an output folder for all emitted files. */ 53 | // "removeComments": true, /* Disable emitting comments. */ 54 | // "noEmit": true, /* Disable emitting files from a compilation. */ 55 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 56 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 57 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 58 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 59 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 60 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 61 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 62 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 63 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 64 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 65 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 66 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 67 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 68 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 69 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 70 | 71 | /* Interop Constraints */ 72 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 73 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 74 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 75 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 76 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 77 | 78 | /* Type Checking */ 79 | "strict": true, /* Enable all strict type-checking options. */ 80 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 81 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 82 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 83 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 84 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 85 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 86 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 87 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 88 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 89 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 90 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 91 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 92 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 93 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 94 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 95 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 96 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 97 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 98 | 99 | /* Completeness */ 100 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 101 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 102 | } 103 | } 104 | --------------------------------------------------------------------------------