├── .eslintrc.yml ├── .github └── workflows │ └── node.js.yml ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── intro.gif └── logo.png ├── babel.config.js ├── docs ├── api-docs │ ├── .nojekyll │ ├── assets │ │ ├── highlight.css │ │ ├── main.js │ │ ├── navigation.js │ │ ├── search.js │ │ └── style.css │ ├── functions │ │ └── useGlitch.html │ ├── index.html │ ├── modules.html │ └── types │ │ └── GlitchHandle.html ├── assets │ ├── index-1e438818.css │ └── index-79941713.js ├── coverage │ ├── clover.xml │ ├── coverage-final.json │ ├── lcov-report │ │ ├── base.css │ │ ├── block-navigation.js │ │ ├── favicon.png │ │ ├── index.html │ │ ├── index.ts.html │ │ ├── prettify.css │ │ ├── prettify.js │ │ ├── sort-arrow-sprite.png │ │ └── sorter.js │ └── lcov.info └── index.html ├── index.html ├── jest.config.ts ├── package-lock.json ├── package.json ├── src ├── docs │ ├── App.tsx │ └── index.css ├── lib │ └── index.ts └── main.tsx ├── test └── useGlitch.test.tsx ├── tsconfig.json ├── tsconfig.node.json ├── typedoc.json ├── vite-docs.config.ts ├── vite-env.d.ts └── vite.config.ts /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | browser: true 3 | es2021: true 4 | extends: 5 | - eslint:recommended 6 | - plugin:react/recommended 7 | - plugin:@typescript-eslint/recommended 8 | overrides: [] 9 | parser: '@typescript-eslint/parser' 10 | parserOptions: 11 | ecmaVersion: latest 12 | sourceType: module 13 | plugins: 14 | - react 15 | - '@typescript-eslint' 16 | rules: 17 | indent: 18 | - error 19 | - 4 20 | linebreak-style: 21 | - error 22 | - unix 23 | quotes: 24 | - error 25 | - single 26 | semi: 27 | - error 28 | - always 29 | -------------------------------------------------------------------------------- /.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: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: ubuntu-latest 16 | 17 | strategy: 18 | matrix: 19 | node-version: [16.x, 18.x, 20.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 | cache: 'npm' 29 | - run: npm ci 30 | - run: npm run build --if-present 31 | - run: npm test 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | /coverage 15 | 16 | # Lib 17 | /lib 18 | /types 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | .DS_Store 25 | *.suo 26 | *.ntvs* 27 | *.njsproj 28 | *.sln 29 | *.sw? 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Benjamin Raymond 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React PowerGlitch 2 | 3 | 4 | 5 | This React library is a wrapper around [PowerGlitch](https://github.com/7PH/powerglitch). PowerGlitch is a standalone library with no external dependencies. It leverages CSS animations to glitch anything on the web, without using a canvas. It weights less than 2kb minified and gzipped. 6 | 7 | - [Original project repository and documentation](https://github.com/7PH/powerglitch) 8 | - [Code coverage report for react-powerglitch](https://7ph.github.io/react-powerglitch/coverage/lcov-report/) 9 | - [API reference for react-powerglitch](https://7ph.github.io/react-powerglitch/api-docs/) 10 | 11 | # Getting started 12 | 13 |

14 | Install 15 | → Glitch 16 | → Customize 17 | → Controls 18 | / TypeScript 19 |

20 | 21 | ## Install 22 | 23 | 1. Install `react-powerglitch` using a package manager 24 | ```bash 25 | npm i --save react-powerglitch 26 | # or 27 | yarn add react-powerglitch 28 | ``` 29 | 30 | 2. Import the `useGlitch` hook from `react-powerglitch` anytime you want to use it. 31 | ```js 32 | import { useGlitch } from 'react-powerglitch' 33 | ``` 34 | 35 | ## Glitch 36 | 37 | In order to glitch something, call `useGlitch()` and store its result in a variable. 38 | ```jsx 39 | function App() { 40 | const glitch = useGlitch(); 41 | 42 | return ( 43 |

react-powerglitch 🌎

44 | ); 45 | } 46 | ``` 47 | 48 | One limitation, when having the `createContainers` option set to true (which is the default), to not place the glitched element as the direct child of a component or a conditional rendering block. E.g. this will **not** work: 49 | ```jsx 50 | <> 51 | {/* Will not work */} 52 | {condition && 53 | 🌎 54 | } 55 | 56 | ``` 57 | 58 | Instead, wrap the glitched element with a container: 59 | ```jsx 60 | <> 61 | {/* Will work */} 62 | {condition && 63 |
64 | 🌎 65 |
66 | } 67 | 68 | ``` 69 | 70 | ## Customize 71 | 72 | You can pass options to customize the glitch effect to `useGlitch`: 73 | ```jsx 74 | function App() { 75 | const glitch = useGlitch({ glitchTimeSpan: false }); 76 | 77 | return ( 78 |

react-powerglitch 🌎

79 | ); 80 | } 81 | ``` 82 | 83 | The `options` props accept any value defined in [the original PowerGlitch library](https://github.com/7PH/powerglitch). 84 | 85 | Take a look at the [playground](https://7ph.github.io/powerglitch/#/playground) to visually find out the best glitch options for your element. 86 | 87 | ## Glitch controls 88 | 89 | The `useGlitch` hook returns an object containing: 90 | - `ref`: A function ref which you should use on the element you want to glitch, as shown in previous sections. 91 | - `startGlitch`: Glitch control functions to start the glitch animation. 92 | - `stopGlitch`: Glitch control functions to stop the glitch animation. 93 | - `setOptions`: A function to change the glitch options. This will update the glitched element with the new options. 94 | 95 | Here is an example: 96 | ```jsx 97 | function App() { 98 | const glitch = useGlitch({ glitchTimeSpan: false }); 99 | 100 | return ( 101 | <> 102 |
103 |

react-powerglitch 🌎

104 |
105 | 108 | 111 | 112 | ); 113 | } 114 | ``` 115 | 116 | ## TypeScript 117 | 118 | The type `GlitchHandle` represents the return type of the `useGlitch` hook. 119 | 120 | Your IDE should automatically identify the return type of `useGlitch` to be `GlitchHandle` and assign it to any variable you assign `useGlitch()` to. In case you want to statically use it, import `GlitchHandle` from `react-powerglitch`. 121 | 122 | ```tsx 123 | import { useGlitch, GlitchHandle } from 'react-powerglitch'; 124 | 125 | function App() { 126 | const glitch: GlitchHandle = useGlitch({ glitchTimeSpan: false }); 127 | 128 | return ( 129 | <> 130 |
131 |

react-powerglitch 🌎

132 |
133 | 136 | 139 | 140 | ); 141 | } 142 | ``` 143 | -------------------------------------------------------------------------------- /assets/intro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7PH/react-powerglitch/e7baa38d47364e67fb83b765b56ec83c9ed9d4b8/assets/intro.gif -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7PH/react-powerglitch/e7baa38d47364e67fb83b765b56ec83c9ed9d4b8/assets/logo.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['@babel/preset-env', {targets: {node: 'current'}}], 4 | '@babel/preset-typescript', 5 | ], 6 | }; 7 | -------------------------------------------------------------------------------- /docs/api-docs/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /docs/api-docs/assets/highlight.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --light-hl-0: #795E26; 3 | --dark-hl-0: #DCDCAA; 4 | --light-hl-1: #000000; 5 | --dark-hl-1: #D4D4D4; 6 | --light-hl-2: #A31515; 7 | --dark-hl-2: #CE9178; 8 | --light-hl-3: #0000FF; 9 | --dark-hl-3: #569CD6; 10 | --light-hl-4: #008000; 11 | --dark-hl-4: #6A9955; 12 | --light-hl-5: #AF00DB; 13 | --dark-hl-5: #C586C0; 14 | --light-hl-6: #001080; 15 | --dark-hl-6: #9CDCFE; 16 | --light-hl-7: #0070C1; 17 | --dark-hl-7: #4FC1FF; 18 | --light-hl-8: #800000; 19 | --dark-hl-8: #808080; 20 | --light-hl-9: #800000; 21 | --dark-hl-9: #569CD6; 22 | --light-hl-10: #E50000; 23 | --dark-hl-10: #9CDCFE; 24 | --light-hl-11: #000000FF; 25 | --dark-hl-11: #D4D4D4; 26 | --light-hl-12: #267F99; 27 | --dark-hl-12: #4EC9B0; 28 | --light-code-background: #FFFFFF; 29 | --dark-code-background: #1E1E1E; 30 | } 31 | 32 | @media (prefers-color-scheme: light) { :root { 33 | --hl-0: var(--light-hl-0); 34 | --hl-1: var(--light-hl-1); 35 | --hl-2: var(--light-hl-2); 36 | --hl-3: var(--light-hl-3); 37 | --hl-4: var(--light-hl-4); 38 | --hl-5: var(--light-hl-5); 39 | --hl-6: var(--light-hl-6); 40 | --hl-7: var(--light-hl-7); 41 | --hl-8: var(--light-hl-8); 42 | --hl-9: var(--light-hl-9); 43 | --hl-10: var(--light-hl-10); 44 | --hl-11: var(--light-hl-11); 45 | --hl-12: var(--light-hl-12); 46 | --code-background: var(--light-code-background); 47 | } } 48 | 49 | @media (prefers-color-scheme: dark) { :root { 50 | --hl-0: var(--dark-hl-0); 51 | --hl-1: var(--dark-hl-1); 52 | --hl-2: var(--dark-hl-2); 53 | --hl-3: var(--dark-hl-3); 54 | --hl-4: var(--dark-hl-4); 55 | --hl-5: var(--dark-hl-5); 56 | --hl-6: var(--dark-hl-6); 57 | --hl-7: var(--dark-hl-7); 58 | --hl-8: var(--dark-hl-8); 59 | --hl-9: var(--dark-hl-9); 60 | --hl-10: var(--dark-hl-10); 61 | --hl-11: var(--dark-hl-11); 62 | --hl-12: var(--dark-hl-12); 63 | --code-background: var(--dark-code-background); 64 | } } 65 | 66 | :root[data-theme='light'] { 67 | --hl-0: var(--light-hl-0); 68 | --hl-1: var(--light-hl-1); 69 | --hl-2: var(--light-hl-2); 70 | --hl-3: var(--light-hl-3); 71 | --hl-4: var(--light-hl-4); 72 | --hl-5: var(--light-hl-5); 73 | --hl-6: var(--light-hl-6); 74 | --hl-7: var(--light-hl-7); 75 | --hl-8: var(--light-hl-8); 76 | --hl-9: var(--light-hl-9); 77 | --hl-10: var(--light-hl-10); 78 | --hl-11: var(--light-hl-11); 79 | --hl-12: var(--light-hl-12); 80 | --code-background: var(--light-code-background); 81 | } 82 | 83 | :root[data-theme='dark'] { 84 | --hl-0: var(--dark-hl-0); 85 | --hl-1: var(--dark-hl-1); 86 | --hl-2: var(--dark-hl-2); 87 | --hl-3: var(--dark-hl-3); 88 | --hl-4: var(--dark-hl-4); 89 | --hl-5: var(--dark-hl-5); 90 | --hl-6: var(--dark-hl-6); 91 | --hl-7: var(--dark-hl-7); 92 | --hl-8: var(--dark-hl-8); 93 | --hl-9: var(--dark-hl-9); 94 | --hl-10: var(--dark-hl-10); 95 | --hl-11: var(--dark-hl-11); 96 | --hl-12: var(--dark-hl-12); 97 | --code-background: var(--dark-code-background); 98 | } 99 | 100 | .hl-0 { color: var(--hl-0); } 101 | .hl-1 { color: var(--hl-1); } 102 | .hl-2 { color: var(--hl-2); } 103 | .hl-3 { color: var(--hl-3); } 104 | .hl-4 { color: var(--hl-4); } 105 | .hl-5 { color: var(--hl-5); } 106 | .hl-6 { color: var(--hl-6); } 107 | .hl-7 { color: var(--hl-7); } 108 | .hl-8 { color: var(--hl-8); } 109 | .hl-9 { color: var(--hl-9); } 110 | .hl-10 { color: var(--hl-10); } 111 | .hl-11 { color: var(--hl-11); } 112 | .hl-12 { color: var(--hl-12); } 113 | pre, code { background: var(--code-background); } 114 | -------------------------------------------------------------------------------- /docs/api-docs/assets/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | "use strict";(()=>{var Pe=Object.create;var ne=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Oe=Object.getOwnPropertyNames;var _e=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var Me=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Fe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Oe(e))!Re.call(t,i)&&i!==n&&ne(t,i,{get:()=>e[i],enumerable:!(r=Ie(e,i))||r.enumerable});return t};var De=(t,e,n)=>(n=t!=null?Pe(_e(t)):{},Fe(e||!t||!t.__esModule?ne(n,"default",{value:t,enumerable:!0}):n,t));var ae=Me((se,oe)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. 3 | `,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[u+1]*i[d+1],u+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),v=s.str.charAt(1),f;v in s.node.edges?f=s.node.edges[v]:(f=new t.TokenSet,s.node.edges[v]=f),s.str.length==1&&(f.final=!0),i.push({node:f,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof se=="object"?oe.exports=n():e.lunr=n()}(this,function(){return t})})()});var re=[];function G(t,e){re.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureActivePageVisible(),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible())}createComponents(e){re.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r}}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(n&&n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let r=document.createElement("p");r.classList.add("warning"),r.textContent="This member is normally hidden due to your filter settings.",n.prepend(r)}}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent="Copied!",e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent="Copy"},100)},1e3)})})}};var ie=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var de=De(ae());async function le(t,e){if(!window.searchData)return;let n=await fetch(window.searchData),r=new Blob([await n.arrayBuffer()]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();t.data=i,t.index=de.Index.load(i.index),e.classList.remove("loading"),e.classList.add("ready")}function he(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:t.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{le(e,t)}),le(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");let s=!1;i.addEventListener("mousedown",()=>s=!0),i.addEventListener("mouseup",()=>{s=!1,t.classList.remove("has-focus")}),r.addEventListener("focus",()=>t.classList.add("has-focus")),r.addEventListener("blur",()=>{s||(s=!1,t.classList.remove("has-focus"))}),Ae(t,i,r,e)}function Ae(t,e,n,r){n.addEventListener("input",ie(()=>{Ne(t,e,n,r)},200));let i=!1;n.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Ve(e,n):s.key=="Escape"?n.blur():s.key=="ArrowUp"?ue(e,-1):s.key==="ArrowDown"?ue(e,1):i=!1}),n.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!n.matches(":focus")&&s.key==="/"&&(n.focus(),s.preventDefault())})}function Ne(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s=i?r.index.search(`*${i}*`):[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=ce(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` 4 | ${ce(l.parent,i)}.${d}`);let v=document.createElement("li");v.classList.value=l.classes??"";let f=document.createElement("a");f.href=r.base+l.url,f.innerHTML=u+d,v.append(f),e.appendChild(v)}}function ue(t,e){let n=t.querySelector(".current");if(!n)n=t.querySelector(e==1?"li:first-child":"li:last-child"),n&&n.classList.add("current");else{let r=n;if(e===1)do r=r.nextElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);else do r=r.previousElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);r&&(n.classList.remove("current"),r.classList.add("current"))}}function Ve(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),e.blur()}}function ce(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(K(t.substring(s,o)),`${K(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(K(t.substring(s))),i.join("")}var Be={"&":"&","<":"<",">":">","'":"'",'"':"""};function K(t){return t.replace(/[&<>"'"]/g,e=>Be[e])}var C=class{constructor(e){this.el=e.el,this.app=e.app}};var F="mousedown",pe="mousemove",B="mouseup",J={x:0,y:0},fe=!1,ee=!1,He=!1,D=!1,me=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(me?"is-mobile":"not-mobile");me&&"ontouchstart"in document.documentElement&&(He=!0,F="touchstart",pe="touchmove",B="touchend");document.addEventListener(F,t=>{ee=!0,D=!1;let e=F=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(pe,t=>{if(ee&&!D){let e=F=="touchstart"?t.targetTouches[0]:t,n=J.x-(e.pageX||0),r=J.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(B,()=>{ee=!1});document.addEventListener("click",t=>{fe&&(t.preventDefault(),t.stopImmediatePropagation(),fe=!1)});var X=class extends C{constructor(n){super(n);this.className=this.el.dataset.toggle||"",this.el.addEventListener(B,r=>this.onPointerUp(r)),this.el.addEventListener("click",r=>r.preventDefault()),document.addEventListener(F,r=>this.onDocumentPointerDown(r)),document.addEventListener(B,r=>this.onDocumentPointerUp(r))}setActive(n){if(this.active==n)return;this.active=n,document.documentElement.classList.toggle("has-"+this.className,n),this.el.classList.toggle("active",n);let r=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(r),setTimeout(()=>document.documentElement.classList.remove(r),500)}onPointerUp(n){D||(this.setActive(!0),n.preventDefault())}onDocumentPointerDown(n){if(this.active){if(n.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(n){if(!D&&this.active&&n.target.closest(".col-sidebar")){let r=n.target.closest("a");if(r){let i=window.location.href;i.indexOf("#")!=-1&&(i=i.substring(0,i.indexOf("#"))),r.href.substring(0,i.length)==i&&setTimeout(()=>this.setActive(!1),250)}}}};var te;try{te=localStorage}catch{te={getItem(){return null},setItem(){}}}var Q=te;var ve=document.head.appendChild(document.createElement("style"));ve.dataset.for="filters";var Y=class extends C{constructor(n){super(n);this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),ve.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } 5 | `}fromLocalStorage(){let n=Q.getItem(this.key);return n?n==="true":this.el.checked}setLocalStorage(n){Q.setItem(this.key,n.toString()),this.value=n,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),document.querySelectorAll(".tsd-index-section").forEach(n=>{n.style.display="block";let r=Array.from(n.querySelectorAll(".tsd-index-link")).every(i=>i.offsetParent==null);n.style.display=r?"none":"block"})}};var Z=class extends C{constructor(n){super(n);this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let r=Q.getItem(this.key);this.el.open=r?r==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update());let i=this.summary.querySelector("a");i&&i.addEventListener("click",()=>{location.assign(i.href)}),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function ge(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,ye(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),ye(t.value)})}function ye(t){document.documentElement.dataset.theme=t}var Le;function be(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",xe),xe())}async function xe(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let n=await(await fetch(window.navigationData)).arrayBuffer(),r=new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip")),i=await new Response(r).json();Le=t.dataset.base+"/",t.innerHTML="";for(let s of i)we(s,t,[]);window.app.createComponents(t),window.app.ensureActivePageVisible()}function we(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-index-accordion`:"tsd-index-accordion",s.dataset.key=i.join("$");let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.innerHTML='',Ee(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let u of t.children)we(u,l,i)}else Ee(t,r,t.class)}function Ee(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));r.href=Le+t.path,n&&(r.className=n),location.href===r.href&&r.classList.add("current"),t.kind&&(r.innerHTML=``),r.appendChild(document.createElement("span")).textContent=t.text}else e.appendChild(document.createElement("span")).textContent=t.text}G(X,"a[data-toggle]");G(Z,".tsd-index-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var Se=document.getElementById("tsd-theme");Se&&ge(Se);var je=new U;Object.defineProperty(window,"app",{value:je});he();be();})(); 6 | /*! Bundled license information: 7 | 8 | lunr/lunr.js: 9 | (** 10 | * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 11 | * Copyright (C) 2020 Oliver Nightingale 12 | * @license MIT 13 | *) 14 | (*! 15 | * lunr.utils 16 | * Copyright (C) 2020 Oliver Nightingale 17 | *) 18 | (*! 19 | * lunr.Set 20 | * Copyright (C) 2020 Oliver Nightingale 21 | *) 22 | (*! 23 | * lunr.tokenizer 24 | * Copyright (C) 2020 Oliver Nightingale 25 | *) 26 | (*! 27 | * lunr.Pipeline 28 | * Copyright (C) 2020 Oliver Nightingale 29 | *) 30 | (*! 31 | * lunr.Vector 32 | * Copyright (C) 2020 Oliver Nightingale 33 | *) 34 | (*! 35 | * lunr.stemmer 36 | * Copyright (C) 2020 Oliver Nightingale 37 | * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt 38 | *) 39 | (*! 40 | * lunr.stopWordFilter 41 | * Copyright (C) 2020 Oliver Nightingale 42 | *) 43 | (*! 44 | * lunr.trimmer 45 | * Copyright (C) 2020 Oliver Nightingale 46 | *) 47 | (*! 48 | * lunr.TokenSet 49 | * Copyright (C) 2020 Oliver Nightingale 50 | *) 51 | (*! 52 | * lunr.Index 53 | * Copyright (C) 2020 Oliver Nightingale 54 | *) 55 | (*! 56 | * lunr.Builder 57 | * Copyright (C) 2020 Oliver Nightingale 58 | *) 59 | */ 60 | -------------------------------------------------------------------------------- /docs/api-docs/assets/navigation.js: -------------------------------------------------------------------------------- 1 | window.navigationData = "data:application/octet-stream;base64,H4sIAAAAAAAAA4uuVipJrShRslJyz8ksSc7wSMxLyUlV0lEqSCzJAIqWVBakFusjy+lllOTmABVkZ+alKFkZGViaG5oa1erAzSktToUoRxiSVpqXXJKZn1esD5dENcXMpDYWANfnPVSKAAAA" -------------------------------------------------------------------------------- /docs/api-docs/assets/search.js: -------------------------------------------------------------------------------- 1 | window.searchData = "data:application/octet-stream;base64,H4sIAAAAAAAAA71WTW+jMBD9L7NXl4D5CvkDbU9724uFIpQ4DVoCCJzdVoj/vgMGjFvcBGmVCxb2e2+GN2ObBqribw071sDvND/CLvAI5MmFww6uNX/OUnE4A4FrleHM6ZofRFrk9WZas87ikiHgkCV1zVEJoCWjGLWj0PHppCgpL0l+zPgkKj5KXm/mS99qBr7vBpPift/Rb2n9mGAzSQJlUvFcfM5LhXJsqtyo+OnOMJaE3g5lDWn9l4/rog6CT86a8H26ho+uRVKJT01wIw2d8mgTZtFHM9xVZszTN5pSlGs9mTEeb8kYfHTEX+nIlLzJEC5+lv25cHdOc8bDDZmCj4aE6wxRybcxAcyHv8OugT+8qnEWWdRyrQhlTinPjt3pKhPFIMXl0gnHw9ovfhBF1SEkZGMDYTahthVGXhwTNjL6hX6ih+EGZ84SzNFgFN8oCa2tTTUU1VC4QZi7JOZqMM8g5mko7C3mLYn5GiwwiAUaCuvC/CWxUINtDWJbDYUFYcGSWKRbaxvUHFmCvuJYasGPr7LyWLuxARvYD+0wXXoNUHy0BDw5BHLYygFFcWxVZ3RvXdS3vvHOw1WpdB2l6xio/fWjGK5iuAYGdnQxbkdFDBQxMhG70/JtONkU01NM38gsyq9EXxFDAxH/PL7ybMVbNBSLVqYlz9IcMSxu23+C+Xz++AgAAA=="; -------------------------------------------------------------------------------- /docs/api-docs/functions/useGlitch.html: -------------------------------------------------------------------------------- 1 | useGlitch | react-powerglitch
2 |
3 | 10 |
11 |
12 |
13 |
14 | 17 |

Function useGlitch

18 |
19 |
    20 | 21 |
  • 22 |

    Hook to glitch one element.

    23 |
    24 |
    25 |

    Parameters

    26 |
      27 |
    • 28 |
      Optional userOptions: RecursivePartial<PowerGlitchOptions>
      29 |

      Options given to PowerGlitch

      30 |
      31 |
    32 |

    Returns GlitchHandle

    A glitch handle with glitch controls, a function to update the options and

    33 | 34 |
37 |
38 | 52 |
57 |
58 |

Generated using TypeDoc

59 |
-------------------------------------------------------------------------------- /docs/api-docs/index.html: -------------------------------------------------------------------------------- 1 | react-powerglitch
2 |
3 | 10 |
11 |
12 |
13 |
14 |

react-powerglitch

15 |

React PowerGlitch

16 | 17 |

This React library is a wrapper around PowerGlitch. PowerGlitch is a standalone library with no external dependencies. It leverages CSS animations to glitch anything on the web, without using a canvas. It weights less than 2kb minified and gzipped.

18 | 23 |

Getting started

24 | Install 25 | → Glitch 26 | → Customize 27 | → Controls 28 | / TypeScript 29 |

30 | 31 |

Install

    32 |
  1. Install react-powerglitch using a package manager

    33 |
    npm i --save react-powerglitch
    # or
    yarn add react-powerglitch 34 |
    35 |
  2. 36 |
  3. Import the useGlitch hook from react-powerglitch anytime you want to use it.

    37 |
    import { useGlitch } from 'react-powerglitch'
     38 | 
    39 |
  4. 40 |
41 |

Glitch

In order to glitch something, call useGlitch() and store its result in a variable.

42 |
function App() {
const glitch = useGlitch();

return (
<h1>react-powerglitch <span ref={glitch.ref}>🌎</span></h1>
);
} 43 |
44 |

One limitation, when having the createContainers option set to true (which is the default), to not place the glitched element as the direct child of a component or a conditional rendering block. E.g. this will not work:

45 |
<>
{/* Will not work */}
{condition &&
<span ref={glitch.ref}>🌎</span>
}
</> 46 |
47 |

Instead, wrap the glitched element with a container:

48 |
<>
{/* Will work */}
{condition &&
<div>
<span ref={glitch.ref}>🌎</span>
</div>
}
</> 49 |
50 |

Customize

You can pass options to customize the glitch effect to useGlitch:

51 |
function App() {
const glitch = useGlitch({ glitchTimeSpan: false });

return (
<h1>react-powerglitch <span ref={glitch.ref}>🌎</span></h1>
);
} 52 |
53 |

The options props accept any value defined in the original PowerGlitch library.

54 |

Take a look at the playground to visually find out the best glitch options for your element.

55 |

Glitch controls

The useGlitch hook returns an object containing:

56 |
    57 |
  • ref: A function ref which you should use on the element you want to glitch, as shown in previous sections.
  • 58 |
  • startGlitch: Glitch control functions to start the glitch animation.
  • 59 |
  • stopGlitch: Glitch control functions to stop the glitch animation.
  • 60 |
  • setOptions: A function to change the glitch options. This will update the glitched element with the new options.
  • 61 |
62 |

Here is an example:

63 |
function App() {
const glitch = useGlitch({ glitchTimeSpan: false });

return (
<>
<div>
<h1 ref={glitch.ref}>react-powerglitch 🌎</h1>
</div>
<button onClick={glitch.startGlitch}>
Start
</button>
<button onClick={glitch.stopGlitch}>
Stop
</button>
</>
);
} 64 |
65 |

TypeScript

The type GlitchHandle represents the return type of the useGlitch hook.

66 |

Your IDE should automatically identify the return type of useGlitch to be GlitchHandle and assign it to any variable you assign useGlitch() to. In case you want to statically use it, import GlitchHandle from react-powerglitch.

67 |
import { useGlitch, GlitchHandle } from 'react-powerglitch';

function App() {
const glitch: GlitchHandle = useGlitch({ glitchTimeSpan: false });

return (
<>
<div>
<h1 ref={glitch.ref}>react-powerglitch 🌎</h1>
</div>
<button onClick={glitch.startGlitch}>
Start
</button>
<button onClick={glitch.stopGlitch}>
Stop
</button>
</>
);
} 68 |
69 |
70 |
71 | 100 |
105 |
106 |

Generated using TypeDoc

107 |
-------------------------------------------------------------------------------- /docs/api-docs/modules.html: -------------------------------------------------------------------------------- 1 | react-powerglitch
2 |
3 | 10 |
11 |
12 |
13 |
14 |

react-powerglitch

15 |
16 |
17 |

Index

18 |
19 |

Type Aliases

20 |
22 |
23 |

Functions

24 |
useGlitch 25 |
26 |
27 | 41 |
46 |
47 |

Generated using TypeDoc

48 |
-------------------------------------------------------------------------------- /docs/api-docs/types/GlitchHandle.html: -------------------------------------------------------------------------------- 1 | GlitchHandle | react-powerglitch
2 |
3 | 10 |
11 |
12 |
13 |
14 | 17 |

Type alias GlitchHandle

18 |
GlitchHandle: {
    ref: ((node) => void);
    startGlitch: (() => void);
    stopGlitch: (() => void);
    setOptions: ((options) => void);
}
19 |

Handle to control the glitch once useGlitch is called.

20 |
21 |
22 |

Type declaration

23 |
    24 |
  • 25 |
    ref: ((node) => void)
    26 |
      27 |
    • 28 |
        29 |
      • (node): void
      • 30 |
      • 31 |

        Function to use as ref for the element to glitch.

        32 |
        33 |
        34 |

        Parameters

        35 |
          36 |
        • 37 |
          node: HTMLElement | null
        38 |

        Returns void

        39 |
  • 40 |
  • 41 |
    startGlitch: (() => void)
    42 |
      43 |
    • 44 |
        45 |
      • (): void
      • 46 |
      • 47 |

        Glitch control to start the glitch animation.

        48 |
        49 |

        Returns void

        50 |
  • 51 |
  • 52 |
    stopGlitch: (() => void)
    53 |
      54 |
    • 55 |
        56 |
      • (): void
      • 57 |
      • 58 |

        Glitch control to stop the glitch animation.

        59 |
        60 |

        Returns void

        61 |
  • 62 |
  • 63 |
    setOptions: ((options) => void)
    64 |
      65 |
    • 66 |
        67 |
      • (options): void
      • 68 |
      • 69 |

        Change the glitch options.

        70 |
        71 |
        72 |

        Parameters

        73 |
          74 |
        • 75 |
          options: RecursivePartial<PowerGlitchOptions>
        76 |

        Returns void

        77 |
78 |
81 |
82 | 96 |
101 |
102 |

Generated using TypeDoc

103 |
-------------------------------------------------------------------------------- /docs/assets/index-1e438818.css: -------------------------------------------------------------------------------- 1 | :root{font-family:Inter,Avenir,Helvetica,Arial,sans-serif;font-size:16px;line-height:24px;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}#root{max-width:1280px;margin:0 auto;padding:2rem;text-align:center}body{margin:0;display:flex;place-items:center;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s;margin-left:.2em;margin-right:.2em}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}} 2 | -------------------------------------------------------------------------------- /docs/coverage/clover.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /docs/coverage/coverage-final.json: -------------------------------------------------------------------------------- 1 | {"/home/braymond/projects/powerglitch/react-powerglitch/src/lib/index.ts": {"path":"/home/braymond/projects/powerglitch/react-powerglitch/src/lib/index.ts","statementMap":{"0":{"start":{"line":1,"column":0},"end":{"line":1,"column":46}},"1":{"start":{"line":2,"column":0},"end":{"line":2,"column":80}},"2":{"start":{"line":39,"column":34},"end":{"line":39,"column":55}},"3":{"start":{"line":44,"column":42},"end":{"line":44,"column":84}},"4":{"start":{"line":44,"column":71},"end":{"line":44,"column":83}},"5":{"start":{"line":44,"column":77},"end":{"line":44,"column":83}},"6":{"start":{"line":45,"column":40},"end":{"line":45,"column":82}},"7":{"start":{"line":45,"column":69},"end":{"line":45,"column":81}},"8":{"start":{"line":45,"column":75},"end":{"line":45,"column":81}},"9":{"start":{"line":51,"column":16},"end":{"line":63,"column":17}},"10":{"start":{"line":54,"column":8},"end":{"line":56,"column":null}},"11":{"start":{"line":55,"column":12},"end":{"line":55,"column":19}},"12":{"start":{"line":60,"column":23},"end":{"line":60,"column":56}},"13":{"start":{"line":61,"column":8},"end":{"line":61,"column":49}},"14":{"start":{"line":61,"column":29},"end":{"line":61,"column":47}},"15":{"start":{"line":62,"column":8},"end":{"line":62,"column":47}},"16":{"start":{"line":62,"column":28},"end":{"line":62,"column":45}},"17":{"start":{"line":65,"column":4},"end":{"line":70,"column":6}},"18":{"start":{"line":35,"column":0},"end":{"line":35,"column":16}}},"fnMap":{"0":{"name":"useGlitch","decl":{"start":{"line":35,"column":16},"end":{"line":35,"column":25}},"loc":{"start":{"line":35,"column":76},"end":{"line":71,"column":1}}},"1":{"name":"(anonymous_1)","decl":{"start":{"line":44,"column":65},"end":{"line":44,"column":68}},"loc":{"start":{"line":44,"column":71},"end":{"line":44,"column":83}}},"2":{"name":"(anonymous_2)","decl":{"start":{"line":44,"column":71},"end":{"line":44,"column":74}},"loc":{"start":{"line":44,"column":77},"end":{"line":44,"column":83}}},"3":{"name":"(anonymous_3)","decl":{"start":{"line":45,"column":63},"end":{"line":45,"column":66}},"loc":{"start":{"line":45,"column":69},"end":{"line":45,"column":81}}},"4":{"name":"(anonymous_4)","decl":{"start":{"line":45,"column":69},"end":{"line":45,"column":72}},"loc":{"start":{"line":45,"column":75},"end":{"line":45,"column":81}}},"5":{"name":"(anonymous_5)","decl":{"start":{"line":51,"column":28},"end":{"line":51,"column":29}},"loc":{"start":{"line":51,"column":57},"end":{"line":63,"column":5}}},"6":{"name":"(anonymous_6)","decl":{"start":{"line":61,"column":23},"end":{"line":61,"column":26}},"loc":{"start":{"line":61,"column":29},"end":{"line":61,"column":47}}},"7":{"name":"(anonymous_7)","decl":{"start":{"line":62,"column":22},"end":{"line":62,"column":25}},"loc":{"start":{"line":62,"column":28},"end":{"line":62,"column":45}}}},"branchMap":{"0":{"loc":{"start":{"line":54,"column":8},"end":{"line":56,"column":null}},"type":"if","locations":[{"start":{"line":54,"column":8},"end":{"line":56,"column":null}}]}},"s":{"0":1,"1":1,"2":5,"3":5,"4":3,"5":3,"6":5,"7":3,"8":3,"9":5,"10":4,"11":2,"12":2,"13":2,"14":2,"15":2,"16":2,"17":5,"18":1},"f":{"0":5,"1":3,"2":3,"3":3,"4":3,"5":4,"6":2,"7":2},"b":{"0":[2]}} 2 | } 3 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/base.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin:0; padding: 0; 3 | height: 100%; 4 | } 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial; 7 | font-size: 14px; 8 | color:#333; 9 | } 10 | .small { font-size: 12px; } 11 | *, *:after, *:before { 12 | -webkit-box-sizing:border-box; 13 | -moz-box-sizing:border-box; 14 | box-sizing:border-box; 15 | } 16 | h1 { font-size: 20px; margin: 0;} 17 | h2 { font-size: 14px; } 18 | pre { 19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; 20 | margin: 0; 21 | padding: 0; 22 | -moz-tab-size: 2; 23 | -o-tab-size: 2; 24 | tab-size: 2; 25 | } 26 | a { color:#0074D9; text-decoration:none; } 27 | a:hover { text-decoration:underline; } 28 | .strong { font-weight: bold; } 29 | .space-top1 { padding: 10px 0 0 0; } 30 | .pad2y { padding: 20px 0; } 31 | .pad1y { padding: 10px 0; } 32 | .pad2x { padding: 0 20px; } 33 | .pad2 { padding: 20px; } 34 | .pad1 { padding: 10px; } 35 | .space-left2 { padding-left:55px; } 36 | .space-right2 { padding-right:20px; } 37 | .center { text-align:center; } 38 | .clearfix { display:block; } 39 | .clearfix:after { 40 | content:''; 41 | display:block; 42 | height:0; 43 | clear:both; 44 | visibility:hidden; 45 | } 46 | .fl { float: left; } 47 | @media only screen and (max-width:640px) { 48 | .col3 { width:100%; max-width:100%; } 49 | .hide-mobile { display:none!important; } 50 | } 51 | 52 | .quiet { 53 | color: #7f7f7f; 54 | color: rgba(0,0,0,0.5); 55 | } 56 | .quiet a { opacity: 0.7; } 57 | 58 | .fraction { 59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 60 | font-size: 10px; 61 | color: #555; 62 | background: #E8E8E8; 63 | padding: 4px 5px; 64 | border-radius: 3px; 65 | vertical-align: middle; 66 | } 67 | 68 | div.path a:link, div.path a:visited { color: #333; } 69 | table.coverage { 70 | border-collapse: collapse; 71 | margin: 10px 0 0 0; 72 | padding: 0; 73 | } 74 | 75 | table.coverage td { 76 | margin: 0; 77 | padding: 0; 78 | vertical-align: top; 79 | } 80 | table.coverage td.line-count { 81 | text-align: right; 82 | padding: 0 5px 0 20px; 83 | } 84 | table.coverage td.line-coverage { 85 | text-align: right; 86 | padding-right: 10px; 87 | min-width:20px; 88 | } 89 | 90 | table.coverage td span.cline-any { 91 | display: inline-block; 92 | padding: 0 5px; 93 | width: 100%; 94 | } 95 | .missing-if-branch { 96 | display: inline-block; 97 | margin-right: 5px; 98 | border-radius: 3px; 99 | position: relative; 100 | padding: 0 4px; 101 | background: #333; 102 | color: yellow; 103 | } 104 | 105 | .skip-if-branch { 106 | display: none; 107 | margin-right: 10px; 108 | position: relative; 109 | padding: 0 4px; 110 | background: #ccc; 111 | color: white; 112 | } 113 | .missing-if-branch .typ, .skip-if-branch .typ { 114 | color: inherit !important; 115 | } 116 | .coverage-summary { 117 | border-collapse: collapse; 118 | width: 100%; 119 | } 120 | .coverage-summary tr { border-bottom: 1px solid #bbb; } 121 | .keyline-all { border: 1px solid #ddd; } 122 | .coverage-summary td, .coverage-summary th { padding: 10px; } 123 | .coverage-summary tbody { border: 1px solid #bbb; } 124 | .coverage-summary td { border-right: 1px solid #bbb; } 125 | .coverage-summary td:last-child { border-right: none; } 126 | .coverage-summary th { 127 | text-align: left; 128 | font-weight: normal; 129 | white-space: nowrap; 130 | } 131 | .coverage-summary th.file { border-right: none !important; } 132 | .coverage-summary th.pct { } 133 | .coverage-summary th.pic, 134 | .coverage-summary th.abs, 135 | .coverage-summary td.pct, 136 | .coverage-summary td.abs { text-align: right; } 137 | .coverage-summary td.file { white-space: nowrap; } 138 | .coverage-summary td.pic { min-width: 120px !important; } 139 | .coverage-summary tfoot td { } 140 | 141 | .coverage-summary .sorter { 142 | height: 10px; 143 | width: 7px; 144 | display: inline-block; 145 | margin-left: 0.5em; 146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; 147 | } 148 | .coverage-summary .sorted .sorter { 149 | background-position: 0 -20px; 150 | } 151 | .coverage-summary .sorted-desc .sorter { 152 | background-position: 0 -10px; 153 | } 154 | .status-line { height: 10px; } 155 | /* yellow */ 156 | .cbranch-no { background: yellow !important; color: #111; } 157 | /* dark red */ 158 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } 159 | .low .chart { border:1px solid #C21F39 } 160 | .highlighted, 161 | .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ 162 | background: #C21F39 !important; 163 | } 164 | /* medium red */ 165 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } 166 | /* light red */ 167 | .low, .cline-no { background:#FCE1E5 } 168 | /* light green */ 169 | .high, .cline-yes { background:rgb(230,245,208) } 170 | /* medium green */ 171 | .cstat-yes { background:rgb(161,215,106) } 172 | /* dark green */ 173 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) } 174 | .high .chart { border:1px solid rgb(77,146,33) } 175 | /* dark yellow (gold) */ 176 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; } 177 | .medium .chart { border:1px solid #f9cd0b; } 178 | /* light yellow */ 179 | .medium { background: #fff4c2; } 180 | 181 | .cstat-skip { background: #ddd; color: #111; } 182 | .fstat-skip { background: #ddd; color: #111 !important; } 183 | .cbranch-skip { background: #ddd !important; color: #111; } 184 | 185 | span.cline-neutral { background: #eaeaea; } 186 | 187 | .coverage-summary td.empty { 188 | opacity: .5; 189 | padding-top: 4px; 190 | padding-bottom: 4px; 191 | line-height: 1; 192 | color: #888; 193 | } 194 | 195 | .cover-fill, .cover-empty { 196 | display:inline-block; 197 | height: 12px; 198 | } 199 | .chart { 200 | line-height: 0; 201 | } 202 | .cover-empty { 203 | background: white; 204 | } 205 | .cover-full { 206 | border-right: none !important; 207 | } 208 | pre.prettyprint { 209 | border: none !important; 210 | padding: 0 !important; 211 | margin: 0 !important; 212 | } 213 | .com { color: #999 !important; } 214 | .ignore-none { color: #999; font-weight: normal; } 215 | 216 | .wrapper { 217 | min-height: 100%; 218 | height: auto !important; 219 | height: 100%; 220 | margin: 0 auto -48px; 221 | } 222 | .footer, .push { 223 | height: 48px; 224 | } 225 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/block-navigation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var jumpToCode = (function init() { 3 | // Classes of code we would like to highlight in the file view 4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; 5 | 6 | // Elements to highlight in the file listing view 7 | var fileListingElements = ['td.pct.low']; 8 | 9 | // We don't want to select elements that are direct descendants of another match 10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` 11 | 12 | // Selecter that finds elements on the page to which we can jump 13 | var selector = 14 | fileListingElements.join(', ') + 15 | ', ' + 16 | notSelector + 17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` 18 | 19 | // The NodeList of matching elements 20 | var missingCoverageElements = document.querySelectorAll(selector); 21 | 22 | var currentIndex; 23 | 24 | function toggleClass(index) { 25 | missingCoverageElements 26 | .item(currentIndex) 27 | .classList.remove('highlighted'); 28 | missingCoverageElements.item(index).classList.add('highlighted'); 29 | } 30 | 31 | function makeCurrent(index) { 32 | toggleClass(index); 33 | currentIndex = index; 34 | missingCoverageElements.item(index).scrollIntoView({ 35 | behavior: 'smooth', 36 | block: 'center', 37 | inline: 'center' 38 | }); 39 | } 40 | 41 | function goToPrevious() { 42 | var nextIndex = 0; 43 | if (typeof currentIndex !== 'number' || currentIndex === 0) { 44 | nextIndex = missingCoverageElements.length - 1; 45 | } else if (missingCoverageElements.length > 1) { 46 | nextIndex = currentIndex - 1; 47 | } 48 | 49 | makeCurrent(nextIndex); 50 | } 51 | 52 | function goToNext() { 53 | var nextIndex = 0; 54 | 55 | if ( 56 | typeof currentIndex === 'number' && 57 | currentIndex < missingCoverageElements.length - 1 58 | ) { 59 | nextIndex = currentIndex + 1; 60 | } 61 | 62 | makeCurrent(nextIndex); 63 | } 64 | 65 | return function jump(event) { 66 | if ( 67 | document.getElementById('fileSearch') === document.activeElement && 68 | document.activeElement != null 69 | ) { 70 | // if we're currently focused on the search input, we don't want to navigate 71 | return; 72 | } 73 | 74 | switch (event.which) { 75 | case 78: // n 76 | case 74: // j 77 | goToNext(); 78 | break; 79 | case 66: // b 80 | case 75: // k 81 | case 80: // p 82 | goToPrevious(); 83 | break; 84 | } 85 | }; 86 | })(); 87 | window.addEventListener('keydown', jumpToCode); 88 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7PH/react-powerglitch/e7baa38d47364e67fb83b765b56ec83c9ed9d4b8/docs/coverage/lcov-report/favicon.png -------------------------------------------------------------------------------- /docs/coverage/lcov-report/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for All files 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files

23 |
24 | 25 |
26 | 100% 27 | Statements 28 | 19/19 29 |
30 | 31 | 32 |
33 | 100% 34 | Branches 35 | 1/1 36 |
37 | 38 | 39 |
40 | 100% 41 | Functions 42 | 8/8 43 |
44 | 45 | 46 |
47 | 100% 48 | Lines 49 | 13/13 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 | 63 |
64 |
65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 |
FileStatementsBranchesFunctionsLines
index.ts 84 |
85 |
100%19/19100%1/1100%8/8100%13/13
98 |
99 |
100 |
101 | 106 | 107 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/index.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for index.ts 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | 19 | 20 |
21 |
22 |

All files index.ts

23 |
24 | 25 |
26 | 100% 27 | Statements 28 | 19/19 29 |
30 | 31 | 32 |
33 | 100% 34 | Branches 35 | 1/1 36 |
37 | 38 | 39 |
40 | 100% 41 | Functions 42 | 8/8 43 |
44 | 45 | 46 |
47 | 100% 48 | Lines 49 | 13/13 50 |
51 | 52 | 53 |
54 |

55 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 56 |

57 | 63 |
64 |
65 |

 66 | 
1 67 | 2 68 | 3 69 | 4 70 | 5 71 | 6 72 | 7 73 | 8 74 | 9 75 | 10 76 | 11 77 | 12 78 | 13 79 | 14 80 | 15 81 | 16 82 | 17 83 | 18 84 | 19 85 | 20 86 | 21 87 | 22 88 | 23 89 | 24 90 | 25 91 | 26 92 | 27 93 | 28 94 | 29 95 | 30 96 | 31 97 | 32 98 | 33 99 | 34 100 | 35 101 | 36 102 | 37 103 | 38 104 | 39 105 | 40 106 | 41 107 | 42 108 | 43 109 | 44 110 | 45 111 | 46 112 | 47 113 | 48 114 | 49 115 | 50 116 | 51 117 | 52 118 | 53 119 | 54 120 | 55 121 | 56 122 | 57 123 | 58 124 | 59 125 | 60 126 | 61 127 | 62 128 | 63 129 | 64 130 | 65 131 | 66 132 | 67 133 | 68 134 | 69 135 | 70 136 | 71 137 | 721x 138 | 1x 139 |   140 |   141 |   142 |   143 |   144 |   145 |   146 |   147 |   148 |   149 |   150 |   151 |   152 |   153 |   154 |   155 |   156 |   157 |   158 |   159 |   160 |   161 |   162 |   163 |   164 |   165 |   166 |   167 |   168 |   169 |   170 |   171 | 1x 172 |   173 |   174 |   175 | 5x 176 |   177 |   178 |   179 |   180 | 5x 181 | 5x 182 |   183 |   184 |   185 |   186 |   187 | 5x 188 |   189 |   190 | 4x 191 | 2x 192 |   193 |   194 |   195 |   196 | 2x 197 | 2x 198 | 2x 199 |   200 |   201 | 5x 202 |   203 |   204 |   205 |   206 |   207 |   208 |  
import { useCallback, useState } from 'react';
209 | import { PowerGlitch, PowerGlitchOptions, RecursivePartial } from 'powerglitch';
210 |  
211 |  
212 | /**
213 |  * Handle to control the glitch once useGlitch is called.
214 |  */
215 | export type GlitchHandle = {
216 |     /**
217 |      * Function to use as ref for the element to glitch.
218 |      */
219 |     ref: (node: HTMLElement | null) => void,
220 |  
221 |     /**
222 |      * Glitch control to start the glitch animation.
223 |      */
224 |     startGlitch: () => void,
225 |  
226 |     /**
227 |      * Glitch control to stop the glitch animation.
228 |      */
229 |     stopGlitch: () => void,
230 |  
231 |     /**
232 |      * Change the glitch options.
233 |      */
234 |     setOptions: (options: RecursivePartial<PowerGlitchOptions>) => void,
235 | };
236 |  
237 | /**
238 |  * Hook to glitch one element.
239 |  * @param userOptions Options given to PowerGlitch
240 |  * @returns A glitch handle with glitch controls, a function to update the options and 
241 |  */
242 | export function useGlitch(userOptions?: RecursivePartial<PowerGlitchOptions>): GlitchHandle {
243 |     /**
244 |      * Copy the options into a state object to avoid unecessary re-renders if the client is re-creating an options object in the main block.
245 |      */
246 |     const [options, setOptions] = useState(userOptions);
247 |  
248 |     /**
249 |      * Placeholder functions to start/stop the glitch, set after actually glitching the element.
250 |      */
251 |     const [startGlitch, setStartGlitch] = useState<(() => void)>(() => () => void 0);
252 |     const [stopGlitch, setStopGlitch] = useState<(() => void)>(() => () => void 0);
253 |  
254 |     /**
255 |      * Will run each time the ref to the node to glitch changes.
256 |      * E.g. after mount or when added/removed due to conditional rendering.
257 |      */
258 |     const ref = useCallback((node: HTMLElement | null) => {
259 |         // If glitching an element inside a conditional render,
260 |         // `node` might not exist at some point, in which case we have nothing to glitch.
261 |         if (! node) {
262 |             return;
263 |         }
264 |         
265 |         // When/if node is visible, glitch it
266 |         // Because of useCallback, we should not glitch an already glitched element, even though the underlying library supports it.
267 |         const result = PowerGlitch.glitch(node, options);
268 |         setStartGlitch(() => result.startGlitch);
269 |         setStopGlitch(() => result.stopGlitch);
270 |     }, [options]);
271 |  
272 |     return {
273 |         ref,
274 |         startGlitch,
275 |         stopGlitch,
276 |         setOptions,
277 |     };
278 | }
279 |  
280 | 281 |
282 |
283 | 288 | 289 | 294 | 295 | 296 | 297 | 298 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/prettify.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /docs/coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/7PH/react-powerglitch/e7baa38d47364e67fb83b765b56ec83c9ed9d4b8/docs/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /docs/coverage/lcov-report/sorter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var addSorting = (function() { 3 | 'use strict'; 4 | var cols, 5 | currentSort = { 6 | index: 0, 7 | desc: false 8 | }; 9 | 10 | // returns the summary table element 11 | function getTable() { 12 | return document.querySelector('.coverage-summary'); 13 | } 14 | // returns the thead element of the summary table 15 | function getTableHeader() { 16 | return getTable().querySelector('thead tr'); 17 | } 18 | // returns the tbody element of the summary table 19 | function getTableBody() { 20 | return getTable().querySelector('tbody'); 21 | } 22 | // returns the th element for nth column 23 | function getNthColumn(n) { 24 | return getTableHeader().querySelectorAll('th')[n]; 25 | } 26 | 27 | function onFilterInput() { 28 | const searchValue = document.getElementById('fileSearch').value; 29 | const rows = document.getElementsByTagName('tbody')[0].children; 30 | for (let i = 0; i < rows.length; i++) { 31 | const row = rows[i]; 32 | if ( 33 | row.textContent 34 | .toLowerCase() 35 | .includes(searchValue.toLowerCase()) 36 | ) { 37 | row.style.display = ''; 38 | } else { 39 | row.style.display = 'none'; 40 | } 41 | } 42 | } 43 | 44 | // loads the search box 45 | function addSearchBox() { 46 | var template = document.getElementById('filterTemplate'); 47 | var templateClone = template.content.cloneNode(true); 48 | templateClone.getElementById('fileSearch').oninput = onFilterInput; 49 | template.parentElement.appendChild(templateClone); 50 | } 51 | 52 | // loads all columns 53 | function loadColumns() { 54 | var colNodes = getTableHeader().querySelectorAll('th'), 55 | colNode, 56 | cols = [], 57 | col, 58 | i; 59 | 60 | for (i = 0; i < colNodes.length; i += 1) { 61 | colNode = colNodes[i]; 62 | col = { 63 | key: colNode.getAttribute('data-col'), 64 | sortable: !colNode.getAttribute('data-nosort'), 65 | type: colNode.getAttribute('data-type') || 'string' 66 | }; 67 | cols.push(col); 68 | if (col.sortable) { 69 | col.defaultDescSort = col.type === 'number'; 70 | colNode.innerHTML = 71 | colNode.innerHTML + ''; 72 | } 73 | } 74 | return cols; 75 | } 76 | // attaches a data attribute to every tr element with an object 77 | // of data values keyed by column name 78 | function loadRowData(tableRow) { 79 | var tableCols = tableRow.querySelectorAll('td'), 80 | colNode, 81 | col, 82 | data = {}, 83 | i, 84 | val; 85 | for (i = 0; i < tableCols.length; i += 1) { 86 | colNode = tableCols[i]; 87 | col = cols[i]; 88 | val = colNode.getAttribute('data-value'); 89 | if (col.type === 'number') { 90 | val = Number(val); 91 | } 92 | data[col.key] = val; 93 | } 94 | return data; 95 | } 96 | // loads all row data 97 | function loadData() { 98 | var rows = getTableBody().querySelectorAll('tr'), 99 | i; 100 | 101 | for (i = 0; i < rows.length; i += 1) { 102 | rows[i].data = loadRowData(rows[i]); 103 | } 104 | } 105 | // sorts the table using the data for the ith column 106 | function sortByIndex(index, desc) { 107 | var key = cols[index].key, 108 | sorter = function(a, b) { 109 | a = a.data[key]; 110 | b = b.data[key]; 111 | return a < b ? -1 : a > b ? 1 : 0; 112 | }, 113 | finalSorter = sorter, 114 | tableBody = document.querySelector('.coverage-summary tbody'), 115 | rowNodes = tableBody.querySelectorAll('tr'), 116 | rows = [], 117 | i; 118 | 119 | if (desc) { 120 | finalSorter = function(a, b) { 121 | return -1 * sorter(a, b); 122 | }; 123 | } 124 | 125 | for (i = 0; i < rowNodes.length; i += 1) { 126 | rows.push(rowNodes[i]); 127 | tableBody.removeChild(rowNodes[i]); 128 | } 129 | 130 | rows.sort(finalSorter); 131 | 132 | for (i = 0; i < rows.length; i += 1) { 133 | tableBody.appendChild(rows[i]); 134 | } 135 | } 136 | // removes sort indicators for current column being sorted 137 | function removeSortIndicators() { 138 | var col = getNthColumn(currentSort.index), 139 | cls = col.className; 140 | 141 | cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); 142 | col.className = cls; 143 | } 144 | // adds sort indicators for current column being sorted 145 | function addSortIndicators() { 146 | getNthColumn(currentSort.index).className += currentSort.desc 147 | ? ' sorted-desc' 148 | : ' sorted'; 149 | } 150 | // adds event listeners for all sorter widgets 151 | function enableUI() { 152 | var i, 153 | el, 154 | ithSorter = function ithSorter(i) { 155 | var col = cols[i]; 156 | 157 | return function() { 158 | var desc = col.defaultDescSort; 159 | 160 | if (currentSort.index === i) { 161 | desc = !currentSort.desc; 162 | } 163 | sortByIndex(i, desc); 164 | removeSortIndicators(); 165 | currentSort.index = i; 166 | currentSort.desc = desc; 167 | addSortIndicators(); 168 | }; 169 | }; 170 | for (i = 0; i < cols.length; i += 1) { 171 | if (cols[i].sortable) { 172 | // add the click event handler on the th so users 173 | // dont have to click on those tiny arrows 174 | el = getNthColumn(i).querySelector('.sorter').parentElement; 175 | if (el.addEventListener) { 176 | el.addEventListener('click', ithSorter(i)); 177 | } else { 178 | el.attachEvent('onclick', ithSorter(i)); 179 | } 180 | } 181 | } 182 | } 183 | // adds sorting functionality to the UI 184 | return function() { 185 | if (!getTable()) { 186 | return; 187 | } 188 | cols = loadColumns(); 189 | loadData(); 190 | addSearchBox(); 191 | addSortIndicators(); 192 | enableUI(); 193 | }; 194 | })(); 195 | 196 | window.addEventListener('load', addSorting); 197 | -------------------------------------------------------------------------------- /docs/coverage/lcov.info: -------------------------------------------------------------------------------- 1 | TN: 2 | SF:src/lib/index.ts 3 | FN:35,useGlitch 4 | FN:44,(anonymous_1) 5 | FN:44,(anonymous_2) 6 | FN:45,(anonymous_3) 7 | FN:45,(anonymous_4) 8 | FN:51,(anonymous_5) 9 | FN:61,(anonymous_6) 10 | FN:62,(anonymous_7) 11 | FNF:8 12 | FNH:8 13 | FNDA:5,useGlitch 14 | FNDA:3,(anonymous_1) 15 | FNDA:3,(anonymous_2) 16 | FNDA:3,(anonymous_3) 17 | FNDA:3,(anonymous_4) 18 | FNDA:4,(anonymous_5) 19 | FNDA:2,(anonymous_6) 20 | FNDA:2,(anonymous_7) 21 | DA:1,1 22 | DA:2,1 23 | DA:35,1 24 | DA:39,5 25 | DA:44,5 26 | DA:45,5 27 | DA:51,5 28 | DA:54,4 29 | DA:55,2 30 | DA:60,2 31 | DA:61,2 32 | DA:62,2 33 | DA:65,5 34 | LF:13 35 | LH:13 36 | BRDA:54,0,0,2 37 | BRF:1 38 | BRH:1 39 | end_of_record 40 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PowerGlitch 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PowerGlitch 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property and type check, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | export default { 6 | coverageDirectory: 'docs/coverage', 7 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 8 | testEnvironment: 'jsdom', 9 | transform: { 10 | '^.+\\.tsx?$': 'ts-jest' 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-powerglitch", 3 | "version": "1.1.0", 4 | "types": "./types/lib/index.d.ts", 5 | "main": "./lib/react-powerglitch.umd.js", 6 | "module": "./lib/react-powerglitch.es.js", 7 | "exports": { 8 | ".": { 9 | "types": "./types/lib/index.d.ts", 10 | "import": "./lib/react-powerglitch.es.js", 11 | "require": "./lib/react-powerglitch.umd.js" 12 | } 13 | }, 14 | "files": [ 15 | "/lib", 16 | "/types" 17 | ], 18 | "scripts": { 19 | "dev": "vite --config vite-docs.config.ts", 20 | "build": "vite --config vite-docs.config.ts build && npm run coverage && npx typedoc && vite build && tsc", 21 | "preview": "vite preview", 22 | "test": "jest", 23 | "coverage": "jest --coverage" 24 | }, 25 | "dependencies": { 26 | "powerglitch": "^2.4.0" 27 | }, 28 | "peerDependencies": { 29 | "react": ">= 16.8.0", 30 | "react-dom": ">= 16.8.0" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.23.0", 34 | "@babel/preset-env": "^7.22.20", 35 | "@babel/preset-typescript": "^7.23.0", 36 | "@testing-library/jest-dom": "^6.1.3", 37 | "@testing-library/react": "^14.0.0", 38 | "@types/jest": "^29.5.5", 39 | "@types/react": "^18.2.24", 40 | "@types/react-dom": "^18.2.8", 41 | "@typescript-eslint/eslint-plugin": "^6.7.3", 42 | "@typescript-eslint/parser": "^6.7.3", 43 | "@vitejs/plugin-react": "^4.1.0", 44 | "babel-jest": "^29.7.0", 45 | "eslint": "^8.50.0", 46 | "eslint-plugin-react": "^7.33.2", 47 | "jest": "^29.7.0", 48 | "jest-environment-jsdom": "^29.7.0", 49 | "jsdom-testing-mocks": "^1.11.0", 50 | "react": "^18.2.0", 51 | "react-dom": "^18.2.0", 52 | "ts-jest": "^29.1.1", 53 | "ts-node": "^10.9.1", 54 | "typedoc": "^0.25.1", 55 | "typescript": "^5.2.2", 56 | "vite": "^4.4.9" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/docs/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { GlitchHandle, useGlitch } from '../lib/'; 3 | 4 | 5 | function App() { 6 | const glitch: GlitchHandle = useGlitch({ hideOverflow: true, glitchTimeSpan: { start: 0, end: 1 } }); 7 | const [show, setShow] = useState(true); 8 | 9 | return ( 10 | <> 11 | {show && 12 |
13 |

react-powerglitch 🌎

14 |
15 | } 16 | 19 | 22 | 25 | 26 | ); 27 | } 28 | 29 | export default App; 30 | -------------------------------------------------------------------------------- /src/docs/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color-scheme: light dark; 8 | color: rgba(255, 255, 255, 0.87); 9 | background-color: #242424; 10 | 11 | font-synthesis: none; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-text-size-adjust: 100%; 16 | } 17 | 18 | #root { 19 | max-width: 1280px; 20 | margin: 0 auto; 21 | padding: 2rem; 22 | text-align: center; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | display: flex; 28 | place-items: center; 29 | min-width: 320px; 30 | min-height: 100vh; 31 | } 32 | 33 | h1 { 34 | font-size: 3.2em; 35 | line-height: 1.1; 36 | } 37 | 38 | button { 39 | border-radius: 8px; 40 | border: 1px solid transparent; 41 | padding: 0.6em 1.2em; 42 | font-size: 1em; 43 | font-weight: 500; 44 | font-family: inherit; 45 | background-color: #1a1a1a; 46 | cursor: pointer; 47 | transition: border-color 0.25s; 48 | margin-left: 0.2em; 49 | margin-right: 0.2em; 50 | } 51 | button:hover { 52 | border-color: #646cff; 53 | } 54 | button:focus, 55 | button:focus-visible { 56 | outline: 4px auto -webkit-focus-ring-color; 57 | } 58 | 59 | @media (prefers-color-scheme: light) { 60 | :root { 61 | color: #213547; 62 | background-color: #ffffff; 63 | } 64 | a:hover { 65 | color: #747bff; 66 | } 67 | button { 68 | background-color: #f9f9f9; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/lib/index.ts: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from 'react'; 2 | import { PowerGlitch, PowerGlitchOptions, RecursivePartial } from 'powerglitch'; 3 | 4 | 5 | /** 6 | * Handle to control the glitch once useGlitch is called. 7 | */ 8 | export type GlitchHandle = { 9 | /** 10 | * Function to use as ref for the element to glitch. 11 | */ 12 | ref: (node: HTMLElement | null) => void, 13 | 14 | /** 15 | * Glitch control to start the glitch animation. 16 | */ 17 | startGlitch: () => void, 18 | 19 | /** 20 | * Glitch control to stop the glitch animation. 21 | */ 22 | stopGlitch: () => void, 23 | 24 | /** 25 | * Change the glitch options. 26 | */ 27 | setOptions: (options: RecursivePartial) => void, 28 | }; 29 | 30 | /** 31 | * Hook to glitch one element. 32 | * @param userOptions Options given to PowerGlitch 33 | * @returns A glitch handle with glitch controls, a function to update the options and 34 | */ 35 | export function useGlitch(userOptions?: RecursivePartial): GlitchHandle { 36 | /** 37 | * Copy the options into a state object to avoid unecessary re-renders if the client is re-creating an options object in the main block. 38 | */ 39 | const [options, setOptions] = useState(userOptions); 40 | 41 | /** 42 | * Placeholder functions to start/stop the glitch, set after actually glitching the element. 43 | */ 44 | const [startGlitch, setStartGlitch] = useState<(() => void)>(() => () => void 0); 45 | const [stopGlitch, setStopGlitch] = useState<(() => void)>(() => () => void 0); 46 | 47 | /** 48 | * Will run each time the ref to the node to glitch changes. 49 | * E.g. after mount or when added/removed due to conditional rendering. 50 | */ 51 | const ref = useCallback((node: HTMLElement | null) => { 52 | // If glitching an element inside a conditional render, 53 | // `node` might not exist at some point, in which case we have nothing to glitch. 54 | if (! node) { 55 | return; 56 | } 57 | 58 | // When/if node is visible, glitch it 59 | // Because of useCallback, we should not glitch an already glitched element, even though the underlying library supports it. 60 | const result = PowerGlitch.glitch(node, options); 61 | setStartGlitch(() => result.startGlitch); 62 | setStopGlitch(() => result.stopGlitch); 63 | }, [options]); 64 | 65 | return { 66 | ref, 67 | startGlitch, 68 | stopGlitch, 69 | setOptions, 70 | }; 71 | } 72 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './docs/App'; 4 | import './docs/index.css'; 5 | 6 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /test/useGlitch.test.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect } from 'react'; 2 | import { mockAnimationsApi } from 'jsdom-testing-mocks'; 3 | import { render } from '@testing-library/react'; 4 | import { useGlitch } from '../src/lib/index'; 5 | 6 | try { 7 | mockAnimationsApi(); 8 | } catch (error) { 9 | console.warn('Unable to mock Web Animation API'); 10 | } 11 | 12 | // Steps is not supported by the Web Animation API mock so we use a different easing for all tests 13 | const BASE_OPTIONS = { 14 | timing: { 15 | easing: 'ease-in-out', 16 | }, 17 | }; 18 | 19 | 20 | describe('useGlitch', () => { 21 | it('is exported', async () => { 22 | expect(useGlitch).toBeTruthy(); 23 | }); 24 | 25 | it('can glitch span element without error', async () => { 26 | function Dummy() { 27 | const glitch = useGlitch({ ...BASE_OPTIONS, slice: { count: 3 } }); 28 | return (
Hello World
); 29 | } 30 | const wrapper = render(); 31 | 32 | // With 3 slices, total layer count should be 3 + 1 = 4 33 | expect(wrapper.container.querySelectorAll('div > div > span').length).toBe(4); 34 | }); 35 | 36 | it('can call startGlitch/stopGlitch after glitch', async () => { 37 | function Dummy() { 38 | const glitch = useGlitch({ ...BASE_OPTIONS }); 39 | useEffect(() => { 40 | glitch.stopGlitch(); 41 | glitch.stopGlitch(); 42 | glitch.startGlitch(); 43 | glitch.startGlitch(); 44 | }, []); 45 | return (
Hello World
); 46 | } 47 | render(); 48 | }); 49 | 50 | it('can call startGlitch/stopGlitch before glitch without an error', async () => { 51 | function Dummy() { 52 | const glitch = useGlitch({ ...BASE_OPTIONS, slice: { count: 3 } }); 53 | glitch.startGlitch(); 54 | glitch.stopGlitch(); 55 | return (
No glitch.
); 56 | } 57 | render(); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "react-jsx", 17 | "declaration": true, 18 | "declarationDir": "types", 19 | "emitDeclarationOnly": true 20 | }, 21 | "include": ["src", "vite-env.d.ts"], 22 | "references": [{ "path": "./tsconfig.node.json" }] 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["src/lib/"], 4 | "out": "docs/api-docs", 5 | "name": "react-powerglitch", 6 | "tsconfig": "./tsconfig.json", 7 | "sort": ["source-order"] 8 | } -------------------------------------------------------------------------------- /vite-docs.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { defineConfig } from 'vite'; 3 | import react from '@vitejs/plugin-react'; 4 | 5 | export default defineConfig({ 6 | plugins: [react()], 7 | build: { 8 | outDir: path.resolve(__dirname, 'docs'), 9 | target: 'es6', 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import { defineConfig } from 'vite'; 3 | import react from '@vitejs/plugin-react'; 4 | 5 | export default defineConfig({ 6 | plugins: [react()], 7 | build: { 8 | outDir: path.resolve(__dirname, 'lib'), 9 | target: 'es6', 10 | lib: { 11 | entry: path.resolve(__dirname, 'src/lib/index.ts'), 12 | name: 'PowerGlitch', 13 | formats: ['umd', 'es'], 14 | fileName: (format) => `react-powerglitch.${format}.js`, 15 | }, 16 | rollupOptions: { 17 | external: ['react', 'react-dom'], 18 | output: { 19 | exports: 'named', 20 | globals: { 21 | 'react': 'React', 22 | }, 23 | }, 24 | }, 25 | }, 26 | }); 27 | --------------------------------------------------------------------------------