From 4c3c09450967880d1551c3948ad021879b41f8bc Mon Sep 17 00:00:00 2001 From: Adam Barton <108860307+rosingrind@users.noreply.github.com> Date: Wed, 22 Feb 2023 08:59:41 +0400 Subject: [PATCH 1/4] Prettier pass + moved to utility usage --- .eslintignore | 4 +- .eslintrc | 13 ++++-- .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 +- README.md | 40 ++++++++++++------ rollup.config.ts | 10 ++--- src/bearing/Slide/index.module.scss | 6 +-- src/bearing/Slide/index.tsx | 5 ++- src/bearing/index.module.scss | 23 +++++------ src/bearing/index.tsx | 20 ++++----- src/easing/index.ts | 21 +++------- test/easing/easing.test.ts | 10 ++--- 17 files changed, 131 insertions(+), 113 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..a7e99dd 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,7 +11,14 @@ "airbnb-typescript", "airbnb/hooks" ], - "overrides": [], + "overrides": [ + { + "files": ["*.test.ts", "*.test.tsx"], + "rules": { + "prefer-arrow-callback": "warn" + } + } + ], "parserOptions": { "ecmaVersion": "latest", "sourceType": "module", @@ -19,7 +26,7 @@ }, "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" } } 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/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..9112ea7 100644 --- a/src/bearing/Slide/index.tsx +++ b/src/bearing/Slide/index.tsx @@ -55,7 +55,7 @@ const Slide: React.FC<{ const end = offset + move; const delta = end - start; - if (timing) + if (timing) { setAnim( animate({ timing: timing, @@ -64,8 +64,9 @@ const Slide: React.FC<{ setCurrent(point); }, duration: speed, - }) + }), ); + } }, [offset, move]); const pos = (((current % len) + len) % len) - half; diff --git a/src/bearing/index.module.scss b/src/bearing/index.module.scss index bee7d45..61fe07f 100644 --- a/src/bearing/index.module.scss +++ b/src/bearing/index.module.scss @@ -3,22 +3,21 @@ .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; @@ -38,8 +37,8 @@ } .btn { - height: 100%; width: 6rem; + height: 100%; cursor: pointer; &:first-of-type { @@ -52,22 +51,22 @@ } .dots { + bottom: 0; display: flex; justify-content: center; width: 100%; - bottom: 0; } .dot { - height: 7px; width: 7px; + height: 7px; margin: 8px; + cursor: pointer; border: 2px solid white; border-radius: 50%; transition: ease-in-out fadetime; - cursor: pointer; &.selected { - background: white; + background-color: white; } } diff --git a/src/bearing/index.tsx b/src/bearing/index.tsx index cf3fe80..977d29d 100644 --- a/src/bearing/index.tsx +++ b/src/bearing/index.tsx @@ -20,9 +20,7 @@ const Carousel: React.FC<{ }> = ({ 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 [slides, setSlides] = useState(data.length <= 3 ? [...data, ...data] : data); const [swipe, setSwipe] = useState(); const [focused, setFocused] = useState(true); const [rnd, setRnd] = useState(0); @@ -31,9 +29,7 @@ const Carousel: React.FC<{ useEffect(() => { window.addEventListener('blur', () => setFocused(false)); window.addEventListener('focus', () => setFocused(true)); - const int = interval - ? setInterval(() => setRnd(Math.random() * 10), interval) - : 0; + const int = interval ? setInterval(() => setRnd(Math.random() * 10), interval) : 0; return () => { window.removeEventListener('blur', () => setFocused(false)); @@ -71,7 +67,11 @@ const Carousel: React.FC<{ }; const cns = { - dot: (selected: boolean) => cx({ dot: true, selected }), + dot: (selected: boolean) => + cx({ + dot: true, + selected, + }), }; return ( @@ -102,11 +102,7 @@ const Carousel: React.FC<{ {data.map((i, key) => ( - getPos(key)} - > + getPos(key)}> ))} getNext()}> diff --git a/src/easing/index.ts b/src/easing/index.ts index b2fadb2..285e2ed 100644 --- a/src/easing/index.ts +++ b/src/easing/index.ts @@ -26,12 +26,10 @@ const bounceOut = (x: number): number => { 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 - pow(-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 easeInOutCubic = (x: number) => (x < 0.5 ? 4 * x * x * x : 1 - pow(-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) => @@ -46,22 +44,13 @@ 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; + 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; + x < 0.5 ? (1 - sqrt(1 - pow(2 * x, 2))) / 2 : (sqrt(1 - pow(-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 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 diff --git a/test/easing/easing.test.ts b/test/easing/easing.test.ts index ee0bcab..4facc12 100644 --- a/test/easing/easing.test.ts +++ b/test/easing/easing.test.ts @@ -1,8 +1,8 @@ -import { easeInBounce } from '../../src/easing'; import { expect } from 'chai'; +import { easeInBounce } from '../../src/easing'; -describe('easing', () => { - it('easeInBounce', () => { - expect(easeInBounce(2)).to.equal(-6.5625); - }); +describe('easing', function fn() { + it('easeInBounce', function () { + expect(easeInBounce(2)).to.equal(-6.5625); + }); }); From df45917c214d2bd82bac3a3119a431f94ef00235 Mon Sep 17 00:00:00 2001 From: Adam Barton <108860307+rosingrind@users.noreply.github.com> Date: Wed, 22 Feb 2023 11:10:38 +0400 Subject: [PATCH 2/4] Tests and easing fix --- .eslintrc | 11 ++++- src/easing/index.ts | 86 ++++++++++++++++++-------------------- test/easing/easing.test.ts | 9 ++-- 3 files changed, 56 insertions(+), 50 deletions(-) diff --git a/.eslintrc b/.eslintrc index a7e99dd..25c58ec 100644 --- a/.eslintrc +++ b/.eslintrc @@ -15,7 +15,12 @@ { "files": ["*.test.ts", "*.test.tsx"], "rules": { - "prefer-arrow-callback": "warn" + "prefer-arrow-callback": [ + "warn", + { + "allowNamedFunctions": true + } + ] } } ], @@ -27,6 +32,8 @@ "plugins": ["react", "mocha", "istanbul"], "rules": { "istanbul/no-ignore-file": "warn", - "istanbul/prefer-ignore-reason": "warn" + "istanbul/prefer-ignore-reason": "warn", + "max-len": "warn", + "no-nested-ternary": "warn" } } diff --git a/src/easing/index.ts b/src/easing/index.ts index 285e2ed..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,59 +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 4facc12..5cf5291 100644 --- a/test/easing/easing.test.ts +++ b/test/easing/easing.test.ts @@ -1,8 +1,11 @@ import { expect } from 'chai'; -import { easeInBounce } from '../../src/easing'; +import { easeInBounce, easeOutBounce } from '../../src/easing'; -describe('easing', function fn() { - it('easeInBounce', function () { +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); + }); }); From e1c1579ce8b30b4333bd73b50c7639c2dfa362f7 Mon Sep 17 00:00:00 2001 From: Adam Barton <108860307+rosingrind@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:52:12 +0400 Subject: [PATCH 3/4] Styles fix for buttons --- .stylelintrc | 8 +++++++- src/bearing/index.module.scss | 31 ++++++++++++++++--------------- src/bearing/index.tsx | 12 +++++++----- 3 files changed, 30 insertions(+), 21 deletions(-) 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/src/bearing/index.module.scss b/src/bearing/index.module.scss index 61fe07f..29015ad 100644 --- a/src/bearing/index.module.scss +++ b/src/bearing/index.module.scss @@ -18,25 +18,26 @@ 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 { + all: unset; width: 6rem; height: 100%; cursor: pointer; @@ -62,11 +63,11 @@ height: 7px; margin: 8px; cursor: pointer; - border: 2px solid white; + border: 2px solid #fff; border-radius: 50%; transition: ease-in-out fadetime; &.selected { - background-color: white; + background-color: #fff; } } diff --git a/src/bearing/index.tsx b/src/bearing/index.tsx index 977d29d..876a982 100644 --- a/src/bearing/index.tsx +++ b/src/bearing/index.tsx @@ -97,17 +97,19 @@ const Carousel: React.FC<{ ))} - getPrev()}> + {data.map((i, key) => ( - getPos(key)}> + ))} - getNext()}> + From d6a1d40f546d408ad37b5d33a6192d5c284df78b Mon Sep 17 00:00:00 2001 From: Adam Barton <108860307+rosingrind@users.noreply.github.com> Date: Wed, 22 Feb 2023 12:52:43 +0400 Subject: [PATCH 4/4] ESLint fixes --- src/bearing/Slide/index.tsx | 75 +++++++++++++++++------------------- src/bearing/index.tsx | 76 ++++++++++++++++--------------------- 2 files changed, 66 insertions(+), 85 deletions(-) diff --git a/src/bearing/Slide/index.tsx b/src/bearing/Slide/index.tsx index 9112ea7..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,61 +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 ( @@ -82,6 +77,4 @@ const Slide: React.FC<{ {src} ); -}; - -export default Slide; +} diff --git a/src/bearing/index.tsx b/src/bearing/index.tsx index 876a982..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,30 +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); @@ -52,26 +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) => (
); -}; - -export default Carousel; +}