react-text-swap-animation 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.eslintrc.js DELETED
@@ -1,74 +0,0 @@
1
- module.exports = {
2
- extends: [
3
- 'react-app',
4
- 'react-app/jest',
5
- ],
6
- rules: {
7
- indent: ['warn', 4],
8
- 'react/jsx-indent': ['warn', 4],
9
- 'react/jsx-indent-props': ['warn', 4],
10
- quotes: [0, 'double', { avoidEscape: true }],
11
- 'quote-props': ['error', 'as-needed'],
12
- 'jsx-quotes': [2, 'prefer-double'],
13
- 'no-undef': 2,
14
- 'id-length': 0,
15
- 'max-len': 0,
16
- 'brace-style': [
17
- 1,
18
- 'stroustrup',
19
- { allowSingleLine: true },
20
- ],
21
- curly: 2,
22
- 'no-use-before-define': [
23
- 1,
24
- 'nofunc',
25
- ],
26
- 'no-unused-vars': [
27
- 1,
28
- {
29
- args: 'none',
30
- ignoreRestSiblings: true,
31
- },
32
- ],
33
- 'arrow-body-style': 0,
34
- 'no-unused-expressions': [
35
- 2,
36
- { allowShortCircuit: true },
37
- ],
38
- 'object-curly-spacing': ['warn', 'always', { objectsInObjects: true }],
39
- 'object-curly-newline': ['warn', { multiline: true }],
40
- 'prefer-const': 'warn',
41
- 'no-restricted-syntax': [
42
- 1,
43
- 'WithStatement',
44
- 'DebuggerStatement',
45
- ],
46
- 'no-underscore-dangle': 0,
47
- 'react/jsx-boolean-value': 0,
48
- 'react/jsx-first-prop-new-line': 0,
49
- 'react/jsx-no-bind': 0,
50
- 'react/no-did-mount-set-state': 0,
51
- 'react/prefer-stateless-function': 0,
52
- 'react/jsx-one-expression-per-line': [0],
53
- // Allow jsx tags inside .js files.
54
- 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
55
- // Disable props spreading (<App {...props} />) warning.
56
- 'react/jsx-props-no-spreading': 0,
57
- // Throw warning instead of error when using array index as a key.
58
- 'react/no-array-index-key': 1,
59
- // Allow using (props) => <Component /> and ({propName}) => <Component /> syntax.
60
- 'react/destructuring-assignment': 'off',
61
- // Disable <Fragment> => <> replacement. Feel free to change
62
- 'react/jsx-fragments': 'off',
63
- // Allow modules with named exports only.
64
- 'import/prefer-default-export': 0,
65
- // Throw warning when <a href="#"> or <a href="javascript:void(0)"> are used. Use <button> instead.
66
- 'jsx-a11y/anchor-is-valid': ['off', { aspects: ['invalidHref'] }],
67
- },
68
- // DeprecationWarning: The 'ecmaFeatures' config file property is deprecated and has no effect. (found in ".eslintrc.js")
69
- // ecmaFeatures: {
70
- // jsx: true,
71
- // modules: true,
72
- // },
73
- parser: 'babel-eslint',
74
- };
@@ -1,16 +0,0 @@
1
- name: Greetings
2
-
3
- on: [pull_request, issues]
4
-
5
- jobs:
6
- greeting:
7
- runs-on: ubuntu-latest
8
- permissions:
9
- issues: write
10
- pull-requests: write
11
- steps:
12
- - uses: actions/first-interaction@v1
13
- with:
14
- repo-token: ${{ secrets.GITHUB_TOKEN }}
15
- issue-message: 'Hey, thanks for raising this issue!'
16
- pr-message: 'You are so AWESOME for chipping in and helping out. Thanks! Keep up the GOOD WORK!'
@@ -1,46 +0,0 @@
1
- # This is a basic workflow to help you get started with Actions
2
-
3
- name: CI
4
-
5
- # Controls when the workflow will run
6
- on:
7
- # Triggers the workflow on push or pull request events but only for the main branch
8
- push:
9
- branches: [ main ]
10
- pull_request:
11
- branches: [ main ]
12
-
13
- # Allows you to run this workflow manually from the Actions tab
14
- workflow_dispatch:
15
-
16
- # A workflow run is made up of one or more jobs that can run sequentially or in parallel
17
- jobs:
18
- # This workflow contains a single job called "build"
19
- build:
20
- # The type of runner that the job will run on
21
- runs-on: ubuntu-latest
22
-
23
- strategy:
24
- matrix:
25
- node-version: [ 14.x, 16.x, 18.x ]
26
- # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
27
-
28
- # Steps represent a sequence of tasks that will be executed as part of the job
29
- steps:
30
- - uses: actions/checkout@v3
31
- - name: Use Node.js ${{ matrix.node-version }}
32
- uses: actions/setup-node@v3
33
- with:
34
- node-version: ${{ matrix.node-version }}
35
- cache: 'npm'
36
- # Runs a single command using the runners shell
37
- - name: Run a one-line script
38
- run: echo Building now...
39
-
40
- # - name: Install python2
41
- # run: apt update && DEBIAN_FRONTEND=noninteractive apt install -y python2 make g++
42
- # - name: Test python2
43
- # run: python2 --version
44
- # - run: npm install sass node-sass@4.14.1
45
- - run: npm i
46
- - run: npm run build-fresh --if-present
package/babel.config.json DELETED
@@ -1,18 +0,0 @@
1
- {
2
- "presets": [
3
- [
4
- "@babel/env",
5
- {
6
- "targets": {
7
- "edge": "17",
8
- "firefox": "60",
9
- "chrome": "67",
10
- "safari": "11.1"
11
- },
12
- "useBuiltIns": "usage",
13
- "corejs": "3.6.5"
14
- }
15
- ],
16
- "@babel/preset-react"
17
- ]
18
- }
@@ -1,156 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = Anagram;
7
-
8
- require("core-js/modules/web.dom-collections.iterator.js");
9
-
10
- var _react = _interopRequireWildcard(require("react"));
11
-
12
- var _utils = require("../utils");
13
-
14
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
15
-
16
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
-
18
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
19
-
20
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
21
-
22
- function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
23
-
24
- /**
25
- * Render and animate from one word to another word and back again.
26
- *
27
- * @param {[{string}]} words The 2 words to animate between.
28
- * @param {AnimationOptions} animationOptions Timing options for when to start, how fast forward/backwards, and when to loop.
29
- * @returns {JSX.Element}
30
- */
31
- function Anagram(_ref) {
32
- let {
33
- words,
34
- animationOptions
35
- } = _ref;
36
- const lettersRefs1 = (0, _react.useRef)([...words[0]].map(() => /*#__PURE__*/(0, _react.createRef)()));
37
- const lettersRefs2 = (0, _react.useRef)([...words[1]].map(() => /*#__PURE__*/(0, _react.createRef)()));
38
- const [swapAnimations, setSwapAnimations] = (0, _react.useState)({});
39
- const playAnimation = (0, _react.useCallback)(function (i) {
40
- let playing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
41
- setSwapAnimations(prevState => {
42
- return _objectSpread(_objectSpread({}, prevState), {}, {
43
- [i]: _objectSpread(_objectSpread({}, prevState[i]), {}, {
44
- playing
45
- })
46
- });
47
- });
48
- }, [setSwapAnimations]);
49
- const {
50
- randomStartMin,
51
- randomStartMax,
52
- randomReverseMin,
53
- randomReverseMax,
54
- loopAnimation,
55
- waitToStart
56
- } = animationOptions;
57
- (0, _react.useEffect)(() => {
58
- const swaps = [];
59
- const destLettersPairedByIndex = [];
60
- [...words[0]].forEach((letter, i) => {
61
- // Find a matching dest character to execute the swap with
62
- const destLetterIndex = [...words[1]].findIndex((destLetter, srcIndex) => {
63
- return destLetter.toLowerCase() === letter.toLowerCase() && destLettersPairedByIndex[srcIndex] !== true;
64
- });
65
- destLettersPairedByIndex[destLetterIndex] = true; // mark this source paired/used
66
-
67
- if (destLetterIndex === -1) {
68
- throw new Error("Not sure how to animate since all source letters were paired already, disappear maybe?");
69
- } // If the text wraps then the offset left isn't correct.
70
-
71
-
72
- const swap = {
73
- src: {
74
- letter,
75
- element: lettersRefs1.current[i].current,
76
- offsetLeft: lettersRefs1.current[i].current.offsetLeft,
77
- offsetTop: lettersRefs1.current[i].current.offsetTop // rect: lettersRefs1.current[i].current.getBoundingClientRect(),
78
-
79
- },
80
- dest: {
81
- letter: words[1][destLetterIndex],
82
- element: lettersRefs2.current[destLetterIndex].current,
83
- offsetLeft: lettersRefs2.current[destLetterIndex].current.offsetLeft,
84
- offsetTop: lettersRefs2.current[destLetterIndex].current.offsetTop // rect: lettersRefs2.current[destLetterIndex].current.getBoundingClientRect(),
85
-
86
- }
87
- };
88
- swaps.push(swap);
89
- });
90
- setSwapAnimations(swaps);
91
-
92
- const animateFunc = () => {
93
- swaps.forEach((swap, i) => {
94
- // Animate each character towards the destination
95
- setTimeout(() => {
96
- playAnimation(i);
97
- }, (0, _utils.randomMinMax)(randomStartMin, randomStartMax)); // Animate each character back to their original location
98
-
99
- setTimeout(() => {
100
- playAnimation(i, false);
101
- }, (0, _utils.randomMinMax)(randomReverseMin, randomReverseMax));
102
- }); // Repeat forever
103
-
104
- setTimeout(() => {
105
- animateFunc();
106
- }, loopAnimation);
107
- }; // Start the process
108
-
109
-
110
- setTimeout(() => {
111
- animateFunc();
112
- }, waitToStart);
113
- }, [lettersRefs1, lettersRefs2, loopAnimation, playAnimation, randomReverseMax, randomReverseMin, randomStartMax, randomStartMin, waitToStart, words]);
114
- return /*#__PURE__*/_react.default.createElement("div", {
115
- className: "anagram-swap"
116
- }, /*#__PURE__*/_react.default.createElement("div", {
117
- className: "word word-1 hidden"
118
- }, [...words[0]].map((letter, i) => {
119
- return /*#__PURE__*/_react.default.createElement("span", {
120
- ref: lettersRefs1.current[i],
121
- className: "letter",
122
- key: "".concat(i).concat(letter)
123
- }, letter);
124
- })), /*#__PURE__*/_react.default.createElement("div", {
125
- className: "word word-2 hidden"
126
- }, [...words[1]].map((letter, i) => {
127
- return /*#__PURE__*/_react.default.createElement("span", {
128
- ref: lettersRefs2.current[i],
129
- className: "letter",
130
- key: "".concat(i).concat(letter)
131
- }, letter);
132
- })), /*#__PURE__*/_react.default.createElement("div", {
133
- className: "word word-animation"
134
- }, [...words[0]].map((letter, i) => {
135
- let letterStyles = {};
136
- const swap = swapAnimations[i];
137
-
138
- if (swap && swap.playing) {
139
- const left = "".concat(swap.dest.offsetLeft - swap.src.offsetLeft, "px");
140
- const top = "".concat(swap.dest.offsetTop - swap.src.offsetTop, "px"); // Trying to fix issue with wrapped text
141
- // const left = `${swap.dest.rect.x - swap.src.rect.x}px`;
142
- // const top = `${swap.dest.rect.y - swap.src.rect.y}px`;
143
-
144
- letterStyles = {
145
- left,
146
- top
147
- };
148
- }
149
-
150
- return /*#__PURE__*/_react.default.createElement("span", {
151
- key: "".concat(i).concat(letter),
152
- className: "letter",
153
- style: letterStyles
154
- }, letter);
155
- })));
156
- }
package/public/index.html DELETED
@@ -1,19 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="theme-color" content="#000000" />
8
- <meta name="description"
9
- content="A React component to use CSS animations to swap letters in 2 words. The text is animated in position after calculating initial and final positions of each letter. Words which are anagrams will animate well, but you can use any words or phrases." />
10
- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
11
- <title>React Text Swap Animation</title>
12
- <link rel="preconnect" href="https://fonts.googleapis.com">
13
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
14
- <link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">
15
- </head>
16
- <body>
17
- <div id="root"></div>
18
- </body>
19
- </html>
package/src/App.css DELETED
@@ -1,12 +0,0 @@
1
- body {
2
- background-color: #1c3d65;
3
- color: #fff;
4
- font-family: 'Open Sans', sans-serif;
5
-
6
- font-size: 42px;
7
- font-weight: bold;
8
- }
9
-
10
- .text-swap .word {
11
- white-space: pre;
12
- }
package/src/index.js DELETED
@@ -1,31 +0,0 @@
1
- import React from 'react';
2
- import ReactDOM from 'react-dom';
3
- import TextSwap from './lib/components';
4
- import './App.css';
5
-
6
- ReactDOM.render(
7
- <React.StrictMode>
8
- <div>
9
- <h1>React Text Swap Animation</h1>
10
- <h2>Demo</h2>
11
-
12
- <TextSwap fontToObserve={{ family: 'Open Sans' }} />
13
-
14
- <br />
15
- <br />
16
-
17
- <TextSwap fontToObserve={{ family: 'Open Sans' }} words={['a witty saying', 'proves nothing']} />
18
-
19
- <br />
20
- <br />
21
-
22
- <TextSwap fontToObserve={{ family: 'Open Sans' }} words={['don\'t be sad it\'s over', 'be happy that it happened']} />
23
-
24
- <br />
25
- <br />
26
-
27
- <TextSwap fontToObserve={{ family: 'Open Sans' }} words={['debit card', 'bad credit']} />
28
- </div>
29
- </React.StrictMode>,
30
- document.getElementById('root'),
31
- );
@@ -1,200 +0,0 @@
1
- import React, { createRef, useCallback, useEffect, useRef, useState } from 'react';
2
- import { randomMinMax, uuidv4 } from '../utils';
3
-
4
- /**
5
- * Render and animate from one word to another word and back again.
6
- *
7
- * @param {[{string}]} words The 2 words to animate between.
8
- * @param {AnimationOptions} animationOptions Timing options for when to start, how fast forward/backwards, and when to loop.
9
- * @returns {JSX.Element}
10
- */
11
- export default function TextSwap({ words, animationOptions }) {
12
- const [swapAnimations, setAnimations] = useState([]);
13
- const lettersRefs1 = useRef([...words[0]].map(() => createRef()));
14
- const lettersRefs2 = useRef([...words[1]].map(() => createRef()));
15
- const updateAnimation = useCallback((i, update = {}) => {
16
- setAnimations((prevState) => {
17
- const newState = [
18
- ...prevState,
19
- ];
20
- newState[i] = {
21
- ...prevState[i],
22
- ...update,
23
- };
24
-
25
- return newState;
26
- });
27
- }, [setAnimations]);
28
-
29
- const {
30
- randomStartMin,
31
- randomStartMax,
32
- randomReverseMin,
33
- randomReverseMax,
34
- loopAnimation,
35
- waitToStart,
36
- } = animationOptions;
37
-
38
- useEffect(() => {
39
- const swaps = [];
40
- const destLettersPairedByIndex = [];
41
-
42
- [...words[0]].forEach((letter, i) => {
43
- // Find a matching destination character to execute the swap with
44
- let destLetterIndex = [...words[1]].findIndex((destLetter, srcIndex) => {
45
- return destLetter.toLowerCase() === letter.toLowerCase()
46
- && destLettersPairedByIndex[srcIndex] !== true;
47
- });
48
-
49
- // If no matching character
50
- if (destLetterIndex === -1) {
51
- // Find a space to swap with
52
- destLetterIndex = [...words[1]].findIndex((destLetter, srcIndex) => {
53
- return destLetter === ' ' && destLettersPairedByIndex[srcIndex] !== true;
54
- });
55
-
56
- // If there was no space, find first non-used space
57
- if (destLetterIndex === -1) {
58
- destLetterIndex = [...words[1]].findIndex((destLetter, srcIndex) => {
59
- return destLettersPairedByIndex[srcIndex] !== true;
60
- });
61
- }
62
- }
63
-
64
- if (destLetterIndex === -1) {
65
- throw new Error(`Not sure how to animate since all source letters were paired already, disappear maybe?`);
66
- }
67
-
68
- destLettersPairedByIndex[destLetterIndex] = true; // mark this source paired/used
69
-
70
- // If the text wraps then the offset left isn't correct.
71
- const swap = {
72
- id: uuidv4(), // for a unique key
73
- letter, // the displayed letter
74
- playing: false, // if this letter is animating to the destination
75
- disappear: false, // if this letter should disappear (temporarily)
76
- // the source location, starting place and letter
77
- src: {
78
- letter: words[0][i],
79
- element: lettersRefs1.current[i].current,
80
- offsetLeft: lettersRefs1.current[i].current.offsetLeft,
81
- offsetTop: lettersRefs1.current[i].current.offsetTop,
82
- rect: lettersRefs1.current[i].current.getBoundingClientRect(),
83
- },
84
- // the destination location and letter
85
- dest: {
86
- letter: words[1][destLetterIndex],
87
- element: lettersRefs2.current[destLetterIndex].current,
88
- offsetLeft: lettersRefs2.current[destLetterIndex].current.offsetLeft,
89
- offsetTop: lettersRefs2.current[destLetterIndex].current.offsetTop,
90
- rect: lettersRefs2.current[destLetterIndex].current.getBoundingClientRect(),
91
- },
92
- };
93
- swaps.push(swap);
94
- });
95
-
96
- setAnimations(swaps);
97
-
98
- const animateFunc = () => {
99
- swaps.forEach((swap, i) => {
100
- // Animate each character towards the destination
101
- const forwardStartTime = randomMinMax(randomStartMin, randomStartMax);
102
- setTimeout(() => {
103
- updateAnimation(i, { playing: true, disappear: false });
104
- if (swap.src.letter !== ' ' && swap.dest.letter === ' ') {
105
- updateAnimation(i, { disappear: true });
106
- }
107
- }, forwardStartTime);
108
-
109
- // Halfway towards the destination, switch to the destination letter
110
- setTimeout(() => {
111
- if (swap.src.letter !== ' ' && swap.dest.letter === ' ') {
112
- // do nothing
113
- }
114
- else {
115
- updateAnimation(i, { letter: swap.dest.letter });
116
- }
117
- }, forwardStartTime + 500);
118
-
119
-
120
- // Animate each character back to their original location
121
- const reverseStartTime = randomMinMax(randomReverseMin, randomReverseMax);
122
- setTimeout(() => {
123
- updateAnimation(i, { playing: false, disappear: false });
124
- if (swap.dest.letter !== ' ' && swap.src.letter === ' ') {
125
- updateAnimation(i, { disappear: true });
126
- }
127
- }, reverseStartTime);
128
-
129
- // Half way back to the initial location, switch to the initial letter
130
- setTimeout(() => {
131
- if (swap.dest.letter !== ' ' && swap.src.letter === ' ') {
132
- // do nothing
133
- }
134
- else {
135
- updateAnimation(i, { letter: swap.src.letter });
136
- }
137
- }, reverseStartTime + 500);
138
- });
139
-
140
- // Repeat forever
141
- setTimeout(() => {
142
- animateFunc();
143
- }, loopAnimation);
144
- };
145
-
146
- // Start the process
147
- setTimeout(() => {
148
- animateFunc();
149
- }, waitToStart);
150
-
151
- }, [lettersRefs1, lettersRefs2, loopAnimation, updateAnimation, randomReverseMax, randomReverseMin, randomStartMax, randomStartMin, waitToStart, words]);
152
-
153
- return (
154
- <div className="text-swap">
155
- <div className="word word-1 hidden">
156
- {
157
- [...words[0]].map((letter, i) => {
158
- // eslint-disable-next-line react/no-array-index-key
159
- return <span ref={lettersRefs1.current[i]} className="letter" key={`${i}${letter}`}>{letter}</span>;
160
- })
161
- }
162
- </div>
163
- <div className="word word-2 hidden">
164
- {
165
- [...words[1]].map((letter, i) => {
166
- // eslint-disable-next-line react/no-array-index-key
167
- return <span ref={lettersRefs2.current[i]} className="letter" key={`${i}${letter}`}>{letter}</span>;
168
- })
169
- }
170
- </div>
171
- <div className="word word-animation">
172
- {
173
- swapAnimations.map((renderedLetter) => {
174
- const { id, letter, playing, disappear, src, dest } = renderedLetter;
175
-
176
- let letterStyles;
177
- if (playing) {
178
- const left = `${dest.rect.x}px`;
179
- letterStyles = { left };
180
- }
181
- else {
182
- const left = `${src.rect.x}px`;
183
- letterStyles = { left };
184
- }
185
-
186
- if (disappear) {
187
- letterStyles.opacity = 0;
188
- }
189
-
190
- return (
191
- <span key={id} className="letter" style={letterStyles}>
192
- {letter}
193
- </span>
194
- );
195
- })
196
- }
197
- </div>
198
- </div>
199
- );
200
- }
@@ -1,21 +0,0 @@
1
- export const DEFAULT_WORDS = ['Text Swap Animation', 'Antitoxin Swamp Tea'];
2
-
3
- /**
4
- * @typedef AnimationOptions Timing options for when to start, how fast to animate forwards, backwards, and when to loop.
5
- * @property {number} randomStartMin The minimum amount of time to randomly wait before starting to animate each letter
6
- * @property {number} randomStartMax The maximum amount of time to randomly wait before starting to animate each letter
7
- * @property {number} randomReverseMin The minimum amount of time to randomly wait before starting to animate each letter in reverse
8
- * @property {number} randomReverseMax The maximum amount of time to randomly wait before starting to animate each letter in reverse
9
- * @property {number} loopAnimation The amount of time for each full loop of the animation
10
- * @property {number} waitToStart The amount of time to wait before beginning the animation on start up
11
- */
12
-
13
- /** @type AnimationOptions */
14
- export const DEFAULT_ANIMATION_OPTIONS = {
15
- randomStartMin: 500,
16
- randomStartMax: 500,
17
- randomReverseMin: 8000,
18
- randomReverseMax: 8000,
19
- loopAnimation: 12000,
20
- waitToStart: 0,
21
- };
@@ -1,32 +0,0 @@
1
- .text-swap {
2
- color: #fff;
3
- flex: 0 0 auto;
4
- align-self: center;
5
- width: 100%;
6
- height: 100%;
7
- margin: 0 auto;
8
- text-align: left;
9
- text-transform: uppercase;
10
- display: flex;
11
- flex-direction: column;
12
- padding: 0;
13
- position: relative; }
14
-
15
- .text-swap .word {
16
- position: relative; }
17
-
18
- .text-swap .word.hidden {
19
- position: absolute;
20
- visibility: hidden;
21
- z-index: -9000; }
22
-
23
- .text-swap .word .letter {
24
- white-space: pre;
25
- z-index: 10;
26
- display: inline-block; }
27
-
28
- .text-swap .word-animation .letter {
29
- z-index: 10;
30
- position: absolute;
31
- /*transition: all, 2s, cubic-bezier(0.1, 0.7, 1.0, 0.1), 2s;*/
32
- transition: all, 2s, ease-in-out, 2s; }
@@ -1,38 +0,0 @@
1
- import React from 'react';
2
- import useFontFaceObserver from 'use-font-face-observer';
3
- import TextSwap from './TextSwap';
4
- import { DEFAULT_ANIMATION_OPTIONS, DEFAULT_WORDS } from './constants';
5
-
6
- import './index.css';
7
-
8
- /**
9
- * @typedef FontToObserve A description of an embedded font to observe and wait until loaded.
10
- * @property {string} [family] The font-family: Roboto, Inter, Open Sans, etc
11
- * @property {string|number} [weight] The font-weight: normal, bold, 800, etc
12
- * @property {string} [style] The font-style: normal, italic, oblique
13
- * @property {string} [stretch] The font stretch: normal, condensed, expanded, etc
14
- */
15
-
16
- /**
17
- * Render and animate from one word to another word and back again.
18
- * @param {[string]} [words] The 2 words to animate between.
19
- * @param {AnimationOptions} [animationOptions] Timing options for when to start, how fast to animate forwards, backwards, and when to loop.
20
- * @param {FontToObserve} [fontToObserve] A description of an embedded font to observe and wait until loaded.
21
- * @returns {JSX.Element|null}
22
- */
23
- export default function Loader({ words = DEFAULT_WORDS, animationOptions = {}, fontToObserve }) {
24
- const animOptions = {
25
- ...DEFAULT_ANIMATION_OPTIONS,
26
- ...animationOptions,
27
- };
28
-
29
- const isFontLoaded = useFontFaceObserver(fontToObserve ? [fontToObserve] : []);
30
-
31
- let word1 = words[0];
32
- let word2 = words[1];
33
- const maxLength = Math.max(word1.length, word2.length);
34
- word1 = word1.padEnd(maxLength, ' ');
35
- word2 = word2.padEnd(maxLength, ' ');
36
-
37
- return isFontLoaded ? <TextSwap words={[word1, word2]} animationOptions={animOptions} /> : null;
38
- }