From 6718d6d1263a7d912aa35f19f2cc91567cb9c662 Mon Sep 17 00:00:00 2001 From: Adam Barton <108860307+rosingrind@users.noreply.github.com> Date: Wed, 22 Feb 2023 13:08:48 +0400 Subject: [PATCH] Update code base (#37) --- .eslintignore | 4 +- .eslintrc | 20 +++++- .github/workflows/codeql.yml | 63 +++++++++---------- .idea/codeStyles/Project.xml | 15 +++-- .idea/jsLinters/eslint.xml | 1 + .idea/prettier.xml | 2 +- .prettierignore | 6 +- .prettierrc | 1 - .stylelintignore | 4 +- .stylelintrc | 8 ++- README.md | 40 ++++++++---- rollup.config.ts | 10 +-- src/bearing/Slide/index.module.scss | 6 +- src/bearing/Slide/index.tsx | 74 ++++++++++------------ src/bearing/index.module.scss | 52 ++++++++-------- src/bearing/index.tsx | 92 ++++++++++++--------------- src/easing/index.ts | 97 ++++++++++++----------------- test/easing/easing.test.ts | 13 ++-- 18 files changed, 261 insertions(+), 247 deletions(-) diff --git a/.eslintignore b/.eslintignore index ff94c04..6d81a70 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,7 +2,9 @@ /dist /easing /coverage -!.*rc .* +!.*rc +!.github +CODEOWNERS LICENSE yarn.lock diff --git a/.eslintrc b/.eslintrc index 1a108c1..25c58ec 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,7 +11,19 @@ "airbnb-typescript", "airbnb/hooks" ], - "overrides": [], + "overrides": [ + { + "files": ["*.test.ts", "*.test.tsx"], + "rules": { + "prefer-arrow-callback": [ + "warn", + { + "allowNamedFunctions": true + } + ] + } + } + ], "parserOptions": { "ecmaVersion": "latest", "sourceType": "module", @@ -19,7 +31,9 @@ }, "plugins": ["react", "mocha", "istanbul"], "rules": { - "istanbul/no-ignore-file": "error", - "istanbul/prefer-ignore-reason": "error" + "istanbul/no-ignore-file": "warn", + "istanbul/prefer-ignore-reason": "warn", + "max-len": "warn", + "no-nested-ternary": "warn" } } diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6145699..069fc24 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -9,17 +9,17 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: 'CodeQL' on: push: - branches: [ "main" ] + branches: ['main'] paths-ignore: - '**.md' - '.github/**' pull_request: # The branches below must be a subset of the branches above - branches: [ "main" ] + branches: ['main'] paths-ignore: - '**.md' - '.github/**' @@ -38,45 +38,44 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'typescript' ] + language: ['typescript'] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Use only 'java' to analyze code written in Java, Kotlin or both # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v3 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # 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 - # queries: security-extended,security-and-quality + # 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 + # queries: security-extended,security-and-quality + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: '/language:${{matrix.language}}' diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 82f8737..c3cc5af 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -2,13 +2,15 @@ - - + \ No newline at end of file diff --git a/.idea/jsLinters/eslint.xml b/.idea/jsLinters/eslint.xml index 34aee22..30c57ad 100644 --- a/.idea/jsLinters/eslint.xml +++ b/.idea/jsLinters/eslint.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml index ced2306..665c203 100644 --- a/.idea/prettier.xml +++ b/.idea/prettier.xml @@ -3,6 +3,6 @@ \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index ff94c04..661ce2e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,7 +2,11 @@ /dist /easing /coverage -!.*rc .* +!.*rc +!.github +CODEOWNERS LICENSE yarn.lock +*.ts +*.tsx diff --git a/.prettierrc b/.prettierrc index 639d2dc..90aa638 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,7 +2,6 @@ "$schema": "http://json.schemastore.org/prettierrc", "arrowParens": "always", "bracketSpacing": true, - "jsxBracketSameLine": false, "jsxSingleQuote": false, "printWidth": 100, "proseWrap": "always", diff --git a/.stylelintignore b/.stylelintignore index ff94c04..6d81a70 100644 --- a/.stylelintignore +++ b/.stylelintignore @@ -2,7 +2,9 @@ /dist /easing /coverage -!.*rc .* +!.*rc +!.github +CODEOWNERS LICENSE yarn.lock diff --git a/.stylelintrc b/.stylelintrc index 2e0dca9..9c61d2b 100644 --- a/.stylelintrc +++ b/.stylelintrc @@ -6,6 +6,12 @@ ], "rules": { "function-parentheses-space-inside": "never-single-line", - "order/properties-alphabetical-order": null + "order/properties-alphabetical-order": null, + "scss/at-rule-no-unknown": [ + true, + { + "ignoreAtRules": ["value"] + } + ] } } diff --git a/README.md b/README.md index 877f338..6f59962 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,44 @@ Bearing is a lightweight TypeScript carousel component for React. -- **Laconic:** The component is built with a feel of minimalism in every step: from minimizing component props to taking care of styling eye-candies. There are also planned options of customizing many style-related things by yourself. -- **Lightweight:** There are no leftover or unnecessary dependencies. You can fell confident of unpacked library size. -- **TypeScript:** This means that not only is there a stable code base, but the library can also be used in both JavaScript and TypeScript projects out of package registry. No needs in additional type definitions search. +- **Laconic:** The component is built with a feel of minimalism in every step: from minimizing + component props to taking care of styling eye-candies. There are also planned options of + customizing many style-related things by yourself. +- **Lightweight:** There are no leftover or unnecessary dependencies. You can fell confident of + unpacked library size. +- **TypeScript:** This means that not only is there a stable code base, but the library can also be + used in both JavaScript and TypeScript projects out of package registry. No needs in additional + type definitions search. ## Installation -You can use Bearing as a `bearing` package on [npm](https://www.npmjs.com/package/bearing). Also there are online playground demonstrations planned. +You can use Bearing as a `bearing` package on [npm](https://www.npmjs.com/package/bearing). Also +there are online playground demonstrations planned. ## Documentation -The documentation wiki is currently in development stage. It will be open for contributing so stay in touch. For now check out [examples](https://github.com/andrewbrodko/bearing/blob/main/README.md#examples). +The documentation wiki is currently in development stage. It will be open for contributing so stay +in touch. For now check out +[examples](https://github.com/andrewbrodko/bearing/blob/main/README.md#examples). ## Examples -We have several examples in the [examples section](https://github.com/andrewbrodko/bearing/wiki/Examples) of wiki. +We have several examples in the +[examples section](https://github.com/andrewbrodko/bearing/wiki/Examples) of wiki. ## Contributing -The main purpose of this repository is to evolve Bearing, share experiences and master many skills. This repo started as my next level pet project. Read below to learn how you can take part in improving Bearing. +The main purpose of this repository is to evolve Bearing, share experiences and master many skills. +This repo started as my next level pet project. Read below to learn how you can take part in +improving Bearing. -To help you get familiar with declared contribution process, there are some common rules of doing so. +To help you get familiar with declared contribution process, there are some common rules of doing +so. ### Rollup -This repo uses [rollup](https://www.npmjs.com/package/rollup) as a package bundler. To perform a local development cycle you need to complete a series of tasks: +This repo uses [rollup](https://www.npmjs.com/package/rollup) as a package bundler. To perform a +local development cycle you need to complete a series of tasks: 1. Clone repo and install package dependencies 2. Create React app for package testing @@ -45,11 +58,14 @@ This repo uses [rollup](https://www.npmjs.com/package/rollup) as a package bundl ### Prettier -Use [Prettier](https://www.npmjs.com/package/prettier) with ide plugin as your main code style checker. +Use [Prettier](https://www.npmjs.com/package/prettier) with ide plugin as your main code style +checker. ### Issues -If you have encountered any bugs or want to offer a feature, feel free to send a pull request or raise an issue. There are two common rules of doing so: +If you have encountered any bugs or want to offer a feature, feel free to send a pull request or +raise an issue. There are two common rules of doing so: - Provide as much related info as you can when raising any issue -- If you have encountered a bug, please post a link to codesandbox with your environment to re-create the issue +- If you have encountered a bug, please post a link to codesandbox with your environment to + re-create the issue diff --git a/rollup.config.ts b/rollup.config.ts index dd84a8e..853cec5 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -1,7 +1,7 @@ -import { RollupOptions } from "rollup"; +import { RollupOptions } from 'rollup'; import typescript from '@rollup/plugin-typescript'; -import postcss from 'rollup-plugin-postcss-modules' +import postcss from 'rollup-plugin-postcss-modules'; import autoprefixer from 'autoprefixer'; const bearing: RollupOptions = { @@ -18,11 +18,11 @@ const bearing: RollupOptions = { sourceMap: true, modules: { generateScopedName: '[local]-[hash:base64:4]', - hashPrefix: 'prefix' + hashPrefix: 'prefix', }, minimize: { - preset: 'default' - } + preset: 'default', + }, }), typescript({ rootDir: './src/bearing', diff --git a/src/bearing/Slide/index.module.scss b/src/bearing/Slide/index.module.scss index 3b2ea09..dba9bb3 100644 --- a/src/bearing/Slide/index.module.scss +++ b/src/bearing/Slide/index.module.scss @@ -1,12 +1,12 @@ .slide { position: absolute; - padding: 0 8px; display: flex; justify-content: center; + padding: 0 8px; - & > img { - height: 100%; + img { width: 100%; + height: 100%; object-fit: cover; } } diff --git a/src/bearing/Slide/index.tsx b/src/bearing/Slide/index.tsx index e5e1110..5fa2555 100644 --- a/src/bearing/Slide/index.tsx +++ b/src/bearing/Slide/index.tsx @@ -1,7 +1,18 @@ -import React from 'react'; -import { useState, useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import styles from './index.module.scss'; +type Props = { + src: string; + animation: { timing: (x: number) => number; speed: number }; + offset: number; + move: number; + len: number; + size: { + width: number; + height: number; + }; +}; + const animate = ({ timing, draw, @@ -13,60 +24,45 @@ const animate = ({ duration: number; callback?: any; }) => { - let start = performance.now(); - let pass = true; - - requestAnimationFrame(function animate(time: number) { + const start = performance.now(); + requestAnimationFrame(function frameCallback(time: number) { let delta = (time - start) / duration; if (delta > 1) delta = 1; - let calc = timing(delta); + const calc = timing(delta); draw(calc); - if (delta < 1 && pass) { - requestAnimationFrame(animate); + if (delta < 1) { + requestAnimationFrame(frameCallback); } else { callback(); } }); - - return { interrupt: () => (pass = false) }; }; -const Slide: React.FC<{ - src: string; - animation: { timing: (x: number) => number; speed: number }; - offset: number; - move: number; - len: number; - size: { - width: number; - height: number; - }; -}> = ({ src, animation: { timing, speed }, offset, move, len, size }) => { +export default function Slide(props: Props) { + const { + src, animation: { timing, speed }, offset, move, len, size, + } = props; + const [current, setCurrent] = useState(offset); - const [anim, setAnim] = useState<{ interrupt: () => void }>(); const half = Math.floor(len / 2); useEffect(() => { - anim?.interrupt(); - const start = current; const end = offset + move; const delta = end - start; - if (timing) - setAnim( - animate({ - timing: timing, - draw: (p) => { - const point = current + delta * p; - setCurrent(point); - }, - duration: speed, - }) - ); - }, [offset, move]); + animate({ + timing, + draw: (p) => { + const point = current + delta * p; + setCurrent(point); + }, + duration: speed, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [offset, move, speed, timing]); const pos = (((current % len) + len) % len) - half; return ( @@ -81,6 +77,4 @@ const Slide: React.FC<{ {src} ); -}; - -export default Slide; +} diff --git a/src/bearing/index.module.scss b/src/bearing/index.module.scss index bee7d45..29015ad 100644 --- a/src/bearing/index.module.scss +++ b/src/bearing/index.module.scss @@ -3,43 +3,43 @@ .wrapper { width: 100%; overflow: hidden; - mask-image: linear-gradient( to right, - rgba(0, 0, 0, 0.2) calc(calc(100% - 1138px) / 16), - rgba(0, 0, 0, 1) calc(calc(100% - 1138px) / 2), - rgba(0, 0, 0, 1) calc(1138px + calc(100% - 1138px) / 2), - rgba(0, 0, 0, 0.2) calc(1138px + calc(100% - 1138px) / 16 * 15) + rgb(0 0 0 / 20%) calc(calc(100% - 1138px) / 16), + rgb(0 0 0 / 100%) calc(calc(100% - 1138px) / 2), + rgb(0 0 0 / 100%) calc(1138px + calc(100% - 1138px) / 2), + rgb(0 0 0 / 20%) calc(1138px + calc(100% - 1138px) / 16 * 15) ); } .carousel { position: relative; - margin: auto; display: flex; - justify-content: center; align-items: center; + justify-content: center; + margin: auto; +} - & > div { - position: relative; - display: flex; - height: 100%; - margin-right: 100%; - } +.carousel > div { + position: relative; + display: flex; + height: 100%; + margin-right: 100%; +} - & > span { - display: contents; +.carousel > span { + display: contents; +} - & > * { - position: absolute; - padding: 8px; - } - } +.carousel > span > * { + position: absolute; + padding: 8px; } .btn { - height: 100%; + all: unset; width: 6rem; + height: 100%; cursor: pointer; &:first-of-type { @@ -52,22 +52,22 @@ } .dots { + bottom: 0; display: flex; justify-content: center; width: 100%; - bottom: 0; } .dot { - height: 7px; width: 7px; + height: 7px; margin: 8px; - border: 2px solid white; + cursor: pointer; + border: 2px solid #fff; border-radius: 50%; transition: ease-in-out fadetime; - cursor: pointer; &.selected { - background: white; + background-color: #fff; } } diff --git a/src/bearing/index.tsx b/src/bearing/index.tsx index cf3fe80..b0920a0 100644 --- a/src/bearing/index.tsx +++ b/src/bearing/index.tsx @@ -1,12 +1,10 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import classNames from 'classnames/bind'; import styles from './index.module.scss'; import './index.scss'; import Slide from './Slide'; -const cx = classNames.bind(styles); - -const Carousel: React.FC<{ +type Props = { slides: string[]; size: { width: number; @@ -17,34 +15,20 @@ const Carousel: React.FC<{ speed: number; interval?: number; }; -}> = ({ slides: data, size, animation, animation: { interval } }) => { - const [current, setCurrent] = useState(0); - const [move, setMove] = useState(0); - const [slides, setSlides] = useState( - data.length <= 3 ? [...data, ...data] : data - ); - const [swipe, setSwipe] = useState(); - const [focused, setFocused] = useState(true); - const [rnd, setRnd] = useState(0); - const [reduced, setReduced] = useState(data); +}; - useEffect(() => { - window.addEventListener('blur', () => setFocused(false)); - window.addEventListener('focus', () => setFocused(true)); - const int = interval - ? setInterval(() => setRnd(Math.random() * 10), interval) - : 0; +const cx = classNames.bind(styles); - return () => { - window.removeEventListener('blur', () => setFocused(false)); - window.removeEventListener('focus', () => () => setFocused(true)); - if (interval) clearInterval(int); - }; - }, []); +export default function Carousel(props: Props) { + const { + slides: data, size, animation, animation: { interval }, + } = props; - useEffect(() => { - if (focused) getNext(); - }, [rnd]); + const [current, setCurrent] = useState(0); + const [move, setMove] = useState(0); + const [slides] = useState(data.length <= 3 ? [...data, ...data, ...data] : data); + const [focused, setFocused] = useState(true); + const [reduced] = useState(data); const getPrev = (m = move, c = current) => { setMove(m + 1); @@ -56,22 +40,28 @@ const Carousel: React.FC<{ setCurrent(i); }; - const getNext = (m = move, c = current) => { - setMove(move - 1); + const getNext = useCallback((m = move, c = current) => { + setMove(m - 1); setCurrent(c + 1 >= reduced.length ? 0 : c + 1); - }; + }, [current, move, reduced.length]); - const getOffsets = () => { - const half = Math.floor(slides.length / 2); - const gap = half - current; - let arr = slides.map((s, i) => i - half); - gap > 0 ? arr.push(...arr.splice(0, gap)) : arr.unshift(...arr.splice(gap)); + useEffect(() => { + window.addEventListener('blur', () => setFocused(false)); + window.addEventListener('focus', () => setFocused(true)); + const int = interval ? setInterval(() => focused && getNext(), interval) : 0; - return arr; - }; + return () => { + window.removeEventListener('blur', () => setFocused(false)); + window.removeEventListener('focus', () => () => setFocused(true)); + if (interval) clearInterval(int); + }; + }, [focused, getNext, interval]); const cns = { - dot: (selected: boolean) => cx({ dot: true, selected }), + dot: (selected: boolean) => cx({ + dot: true, + selected, + }), }; return ( @@ -86,7 +76,7 @@ const Carousel: React.FC<{
{slides.map((s, key) => ( - getPrev()}> + {data.map((i, key) => ( - getPos(key)} - > + ))} - getNext()}> +
); -}; - -export default Carousel; +} diff --git a/src/easing/index.ts b/src/easing/index.ts index b2fadb2..f54930a 100644 --- a/src/easing/index.ts +++ b/src/easing/index.ts @@ -1,8 +1,9 @@ -const pow = Math.pow; -const sqrt = Math.sqrt; -const sin = Math.sin; -const cos = Math.cos; -const PI = Math.PI; +const { + sqrt, + sin, + cos, + PI, +} = Math; const c1 = 1.70158; const c2 = c1 * 1.525; const c3 = c1 + 1; @@ -15,70 +16,54 @@ const bounceOut = (x: number): number => { if (x < 1 / d1) { return n1 * x * x; - } else if (x < 2 / d1) { - return n1 * (x -= 1.5 / d1) * x + 0.75; - } else if (x < 2.5 / d1) { - return n1 * (x -= 2.25 / d1) * x + 0.9375; - } else { - return n1 * (x -= 2.625 / d1) * x + 0.984375; } + if (x < 2 / d1) { + const dx = x - 1.5 / d1; + return n1 * (x - 1.5 / d1) * dx + 0.75; + } + if (x < 2.5 / d1) { + const dx = x - 2.25 / d1; + return n1 * (x - 2.25 / d1) * dx + 0.9375; + } + const dx = x - 2.625 / d1; + return n1 * (x - 2.625 / d1) * dx + 0.984375; }; export const easeInQuad = (x: number) => x * x; export const easeOutQuad = (x: number) => 1 - (1 - x) * (1 - x); -export const easeInOutQuad = (x: number) => - x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2; +export const easeInOutQuad = (x: number) => (x < 0.5 ? 2 * x * x : 1 - (-2 * x + 2) ** 2 / 2); export const easeInCubic = (x: number) => x * x * x; -export const easeOutCubic = (x: number) => 1 - pow(1 - x, 3); -export const easeInOutCubic = (x: number) => - x < 0.5 ? 4 * x * x * x : 1 - pow(-2 * x + 2, 3) / 2; +export const easeOutCubic = (x: number) => 1 - (1 - x) ** 3; +export const easeInOutCubic = (x: number) => (x < 0.5 ? 4 * x * x * x : 1 - (-2 * x + 2) ** 3 / 2); export const easeInQuart = (x: number) => x * x * x * x; -export const easeOutQuart = (x: number) => 1 - pow(1 - x, 4); -export const easeInOutQuart = (x: number) => - x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2; +export const easeOutQuart = (x: number) => 1 - (1 - x) ** 4; +export const easeInOutQuart = (x: number) => (x < 0.5 ? 8 * x * x * x * x : 1 - (-2 * x + 2) ** 4 / 2); export const easeInQuint = (x: number) => x * x * x * x * x; -export const easeOutQuint = (x: number) => 1 - pow(1 - x, 5); -export const easeInOutQuint = (x: number) => - x < 0.5 ? 16 * x * x * x * x * x : 1 - pow(-2 * x + 2, 5) / 2; +export const easeOutQuint = (x: number) => 1 - (1 - x) ** 5; +export const easeInOutQuint = (x: number) => (x < 0.5 ? 16 * x * x * x * x * x : 1 - (-2 * x + 2) ** 5 / 2); export const easeInSine = (x: number) => 1 - cos((x * PI) / 2); export const easeOutSine = (x: number) => sin((x * PI) / 2); export const easeInOutSine = (x: number) => -(cos(PI * x) - 1) / 2; -export const easeInExpo = (x: number) => (x === 0 ? 0 : pow(2, 10 * x - 10)); -export const easeOutExpo = (x: number) => (x === 1 ? 1 : 1 - pow(2, -10 * x)); -export const easeInOutExpo = (x: number) => - x === 0 - ? 0 - : x === 1 - ? 1 - : x < 0.5 - ? pow(2, 20 * x - 10) / 2 - : (2 - pow(2, -20 * x + 10)) / 2; -export const easeInCirc = (x: number) => 1 - sqrt(1 - pow(x, 2)); -export const easeOutCirc = (x: number) => sqrt(1 - pow(x - 1, 2)); -export const easeInOutCirc = (x: number) => - x < 0.5 - ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 - : (sqrt(1 - pow(-2 * x + 2, 2)) + 1) / 2; +export const easeInExpo = (x: number) => (x === 0 ? 0 : 2 ** (10 * x - 10)); +export const easeOutExpo = (x: number) => (x === 1 ? 1 : 1 - 2 ** (-10 * x)); +export const easeInOutExpo = (x: number) => (x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? 2 ** (20 * x - 10) / 2 : (2 - 2 ** (-20 * x + 10)) / 2); +export const easeInCirc = (x: number) => 1 - sqrt(1 - x ** 2); +export const easeOutCirc = (x: number) => sqrt(1 - (x - 1) ** 2); +export const easeInOutCirc = (x: number) => (x < 0.5 ? (1 - sqrt(1 - (2 * x) ** 2)) / 2 : (sqrt(1 - (-2 * x + 2) ** 2) + 1) / 2); export const easeInBack = (x: number) => c3 * x * x * x - c1 * x * x; -export const easeOutBack = (x: number) => - 1 + c3 * pow(x - 1, 3) + c1 * pow(x - 1, 2); -export const easeInOutBack = (x: number) => - x < 0.5 - ? (pow(2 * x, 2) * ((c2 + 1) * 2 * x - c2)) / 2 - : (pow(2 * x - 2, 2) * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2; -export const easeInElastic = (x: number) => - x === 0 ? 0 : x === 1 ? 1 : -pow(2, 10 * x - 10) * sin((x * 10 - 10.75) * c4); -export const easeOutElastic = (x: number) => - x === 0 ? 0 : x === 1 ? 1 : pow(2, -10 * x) * sin((x * 10 - 0.75) * c4) + 1; -export const easeInOutElastic = (x: number) => - x === 0 - ? 0 - : x === 1 +export const easeOutBack = (x: number) => 1 + c3 * (x - 1) ** 3 + c1 * (x - 1) ** 2; +export const easeInOutBack = (x: number) => (x < 0.5 + ? ((2 * x) ** 2 * ((c2 + 1) * 2 * x - c2)) / 2 + : ((2 * x - 2) ** 2 * ((c2 + 1) * (x * 2 - 2) + c2) + 2) / 2); +export const easeInElastic = (x: number) => (x === 0 ? 0 : x === 1 ? 1 : -(2 ** (10 * x - 10)) * sin((x * 10 - 10.75) * c4)); +export const easeOutElastic = (x: number) => (x === 0 ? 0 : x === 1 ? 1 : 2 ** (-10 * x) * sin((x * 10 - 0.75) * c4) + 1); +export const easeInOutElastic = (x: number) => (x === 0 + ? 0 + : x === 1 ? 1 : x < 0.5 - ? -(pow(2, 20 * x - 10) * sin((20 * x - 11.125) * c5)) / 2 - : (pow(2, -20 * x + 10) * sin((20 * x - 11.125) * c5)) / 2 + 1; + ? -(2 ** (20 * x - 10) * sin((20 * x - 11.125) * c5)) / 2 + : (2 ** (-20 * x + 10) * sin((20 * x - 11.125) * c5)) / 2 + 1); export const easeInBounce = (x: number) => 1 - bounceOut(1 - x); export const easeOutBounce = bounceOut; -export const easeInOutBounce = (x: number) => - x < 0.5 ? (1 - bounceOut(1 - 2 * x)) / 2 : (1 + bounceOut(2 * x - 1)) / 2; +export const easeInOutBounce = (x: number) => (x < 0.5 ? (1 - bounceOut(1 - 2 * x)) / 2 : (1 + bounceOut(2 * x - 1)) / 2); diff --git a/test/easing/easing.test.ts b/test/easing/easing.test.ts index ee0bcab..5cf5291 100644 --- a/test/easing/easing.test.ts +++ b/test/easing/easing.test.ts @@ -1,8 +1,11 @@ -import { easeInBounce } from '../../src/easing'; import { expect } from 'chai'; +import { easeInBounce, easeOutBounce } from '../../src/easing'; -describe('easing', () => { - it('easeInBounce', () => { - expect(easeInBounce(2)).to.equal(-6.5625); - }); +describe('easing', function suite() { + it('easeInBounce', function fn() { + expect(easeInBounce(2)).to.equal(-6.5625); + }); + it('easeOutBounce', function fn() { + expect(easeOutBounce(2)).to.equal(9.25); + }); });