├── .babelrc
├── .editorconfig
├── .eslintrc
├── .gitignore
├── .nvmrc
├── .travis.yml
├── LICENSE
├── README.md
├── dist
├── sal.css
└── sal.js
├── index.d.ts
├── index.html
├── package.json
├── postcss.config.js
├── src
├── sal.js
└── sal.scss
├── test
├── config
│ └── browser.js
├── fixtures
│ ├── default.html
│ ├── disabled.html
│ ├── repeat-once-attr.html
│ ├── repeat.html
│ ├── reset.html
│ └── update.html
├── index.test.js
└── mocks
│ └── styleMock.js
├── webpack.config.js
├── website
├── images
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon.ico
│ ├── logo.svg
│ └── manifest.json
├── styles.css
└── template
│ ├── index.pug
│ └── shape.pug
└── yarn.lock
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "useBuiltIns": "entry",
7 | "corejs": 3
8 | }
9 | ]
10 | ],
11 | "env": {
12 | "test": {
13 | "presets": [
14 | [
15 | "@babel/preset-env",
16 | {
17 | "targets": {
18 | "node": "current"
19 | }
20 | }
21 | ]
22 | ],
23 | "plugins": [
24 | "@babel/transform-runtime"
25 | ]
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb-base",
3 | "parser": "babel-eslint",
4 | "parserOptions": {
5 | "ecmaVersion": 6
6 | },
7 | "rules": {
8 | "no-unused-vars": 2,
9 | "max-len": [2, 80, 2],
10 | "no-console": 1,
11 | "prefer-arrow-callback": 2,
12 | "func-style": [
13 | 2,
14 | "expression",
15 | {
16 | "allowArrowFunctions": true
17 | }
18 | ],
19 | "arrow-body-style": [2, "as-needed"],
20 | "array-bracket-spacing": ["error", "never"],
21 | "computed-property-spacing": ["error", "never"],
22 | "no-duplicate-imports": "error",
23 | "object-curly-spacing": ["error", "always"]
24 | },
25 | "env": {
26 | "node": true,
27 | "browser": true,
28 | "es6": true,
29 | "jest": true
30 | },
31 | "globals": {
32 | "process": "readonly",
33 | "module": "readonly"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Numerous always-ignore extensions
2 | *.diff
3 | *.err
4 | *.log
5 | *.orig
6 | *.rej
7 | *.swo
8 | *.swp
9 | *.vi
10 | *.zip
11 | *~
12 |
13 | # OS or Editor folders
14 | ._*
15 | .cache
16 | .DS_Store
17 | .idea
18 | .project
19 | .settings
20 | .tmproj
21 | *.esproj
22 | *.sublime-project
23 | *.sublime-workspace
24 | nbproject
25 | Thumbs.db
26 |
27 | # Folders to ignore
28 | bower_components
29 | node_modules
30 |
31 | # Dev files to ignore
32 | dist/*.map
33 |
34 | # waiting for https://github.com/GoogleChromeLabs/size-plugin/issues/28
35 | size-plugin.json
36 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | lts/erbium
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - lts/erbium
4 | script:
5 | - npm run build
6 | - npm run test
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Mirosław Ciastek
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 | # Sal [](https://www.npmjs.com/package/sal.js) [](https://github.com/mciastek/sal/blob/master/LICENSE) [](https://travis-ci.com/mciastek/sal)
2 |
3 | Performance focused, lightweight (less than **2.8 kb**) scroll animation library, written in vanilla JavaScript. No dependencies!
4 |
5 | **Sal** (_Scroll Animation Library_) was created to provide a performant and lightweight solution for animating elements on scroll. It's based on the [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API), which gives amazing performance in terms of checking the element's presence in the viewport.
6 |
7 | **Note:** Intersection Observer API is an experimental technology so be sure to consult the [browser compatibility table](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Browser_compatibility) and consider using a [polyfill](https://github.com/w3c/IntersectionObserver/tree/master/polyfill).
8 |
9 | ## Table of Contents
10 | - [Install](#install)
11 | - [Usage](#usage)
12 | - [Animations](#animations)
13 | - [Options](#options)
14 | - [API](#api)
15 | - [Events](#events)
16 | - [Misc](#misc)
17 | - [License](#license)
18 |
19 | ## Install
20 |
21 | ```sh
22 | # Usage with NPM
23 | $ npm install --save sal.js
24 |
25 | # and with Yarn
26 | $ yarn add sal.js
27 | ```
28 |
29 | Load it with your favorite module loader or use as a global variable
30 |
31 | ```js
32 | // ES6 modules
33 | import sal from 'sal.js'
34 |
35 | // CommonJS modules
36 | var sal = require('sal.js')
37 | ```
38 |
39 | And remember to add styles
40 |
41 | ```scss
42 | // Webpack
43 | @import '~sal.js/sal.css';
44 |
45 | // Other
46 | @import './node_modules/sal.js/dist/sal.css';
47 | ```
48 |
49 | ## Usage
50 |
51 | In HTML, add a `data-sal` attribute with the animation name as value, e.g.:
52 |
53 | ```html
54 |
55 | ```
56 |
57 | Then simply initialize Sal in your script file:
58 |
59 | ```js
60 | sal();
61 | ```
62 |
63 | It will look for all elements with a `data-sal` attribute and launch their animation when in viewport.
64 |
65 | ## Animations
66 | In **sal.js** you can easily change animation's options, by adding a proper `data` attribute:
67 | - `data-sal-duration` - changes duration of the animation (from 200 to 2000 ms)
68 | - `data-sal-delay` - adds delay to the animation (from 5 to 1000 ms)
69 | - `data-sal-easing` - sets easing for the animation (see [easings.net](https://easings.net/) for reference)
70 |
71 | For example:
72 | ```html
73 |
78 | ```
79 |
80 | The library supports several animations:
81 | - `fade`
82 | - `slide-up`
83 | - `slide-down`
84 | - `slide-left`
85 | - `slide-right`
86 | - `zoom-in`
87 | - `zoom-out`
88 | - `flip-up`
89 | - `flip-down`
90 | - `flip-left`
91 | - `flip-right`
92 |
93 | ### Duration and delay
94 |
95 | Additionaly, when you want to customise animation's properties - `duration`, `delay` and `easing`, you can use [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) to set any value you want. See the following example:
96 |
97 | ```html
98 |
102 | ```
103 |
104 | Supported custom properties:
105 | - `--sal-duration`
106 | - `--sal-delay`
107 | - `--sal-easing`
108 |
109 | Remember, that you can use only data attributes (e.g. `data-sal-delay`) or CSS custom properties (e.g. `--sal-delay`). Data attributes have precedence over CSS custom properties.
110 |
111 | ### Repeating animation
112 |
113 | By default every animation is played once. You can change it by setting `once` option to `false` (see [Options](#options)). What's more, it's possible to override this option for an animated element by adding one of the following attributes:
114 | - `data-sal-repeat` - forces animation replay
115 | - `data-sal-once` - plays animation once
116 |
117 | ## Options
118 |
119 | | Property | Type | Description | Default |
120 | |---------------------------|-------------|---------------|---------|
121 | | `threshold` | Number | Percentage of an element's area that needs to be visible to launch animation (see [docs](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/thresholds)) | `0.5` |
122 | | `once` | Boolean | Defines if animation needs to be launched once. Can be overridden, see [Repeating Animation](#repeating-animation). | `true` |
123 | | `disabled` | Boolean or Function | Flag (or a function returning boolean) for disabling animations | `false` |
124 |
125 | You can set options during Sal's initialization, e.g.:
126 |
127 | ```js
128 | sal({
129 | threshold: 1,
130 | once: false,
131 | });
132 | ```
133 |
134 | ### Advanced options
135 |
136 | | Property | Type | Description | Default |
137 | |---------------------------|-------------|---------------|---------|
138 | | `root` | Element or null | The element that is used as the viewport for checking visibility of the target (see [docs](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root)) | `window` |
139 | | `selector` | String | Selector of the elements to be animated | `[data-sal]` |
140 | | `animateClassName` | String | Class name which triggers animation | `sal-animate` |
141 | | `disabledClassName` | String | Class name which defines the disabled state | `sal-disabled` |
142 | | `rootMargin` | String | Corresponds to root's bounding box margin (see [docs](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin)) | `0% 50%` |
143 | | `enterEventName` | String | Enter event name (see [Events](#events)) | `sal:in` |
144 | | `exitEventName` | String | Exit event name (see [Events](#events)) | `sal:out` |
145 |
146 | ## API
147 |
148 | | Method name | Description |
149 | |---------------------------|-------------|
150 | | `enable` | Enables animations |
151 | | `disable` | Disables animations |
152 | | `reset` | Resets instance and allows to pass new options (see [Options](#options)) |
153 | | `update` | Updates observer with new elements to animated. Useful for dynamically injected HTML. |
154 |
155 | Public methods are available after Sal's initialization:
156 |
157 | ```js
158 | const scrollAnimations = sal();
159 |
160 | scrollAnimations.disable();
161 | ```
162 |
163 | ### Changing options after intialization
164 |
165 | If you want to change Sal's options once it's been initialized, you should use `reset` method, that allows you to pass new set of options. It can be useful, when you would like to provide different options for specific viewport sizes.
166 |
167 | ```js
168 | const scrollAnimations = sal();
169 |
170 | // Provide new options
171 | scrollAnimations.reset({
172 | selector: 'animated-element',
173 | once: true,
174 | });
175 | ```
176 |
177 | ## Events
178 |
179 | This library supports events, fired when element is entering or exiting viewport (they are named `sal:in` and `sal:out` by default). Property `detail` is [IntersectionObserverEntry](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry) object.
180 |
181 |
182 | You can attach listener to specific element.
183 |
184 | ```js
185 | // Get element with ".animated" class, which has "data-sal" attribute
186 | const element = document.querySelector('.animated');
187 |
188 | element.addEventListener('sal:in', ({ detail }) => {
189 | console.log('entering', detail.target);
190 | });
191 | ```
192 |
193 | or to the whole document
194 |
195 | ```js
196 | document.addEventListener('sal:out', ({ detail }) => {
197 | console.log('exiting', detail.target);
198 | });
199 | ```
200 |
201 | **Note:** This library uses [Custom Event](https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent) to trigger events on animated elements. Check the [compatibility table](https://caniuse.com/#search=custom%20event) to know if your browser supports it and use a [polyfill](https://github.com/kumarharsh/custom-event-polyfill) if needed.
202 |
203 | ## Misc
204 |
205 | ### No-JS support
206 |
207 | If you aim to support users that don't allow sites to use JavaScript, you should consider disabling animations' styles in the first place. You can use `` element to inject required CSS. Here's an example:
208 |
209 | ```html
210 |
227 | ```
228 |
229 | ## License
230 |
231 | Created by [Mirek Ciastek](https://github.com/mciastek). Released under the [MIT License](https://github.com/mciastek/sal/blob/master/LICENSE).
232 |
--------------------------------------------------------------------------------
/dist/sal.css:
--------------------------------------------------------------------------------
1 | [data-sal]{transition-delay:0s;transition-delay:var(--sal-delay,0s);transition-duration:.2s;transition-duration:var(--sal-duration,.2s);transition-timing-function:ease;transition-timing-function:var(--sal-easing,ease)}[data-sal][data-sal-duration="200"]{transition-duration:.2s}[data-sal][data-sal-duration="250"]{transition-duration:.25s}[data-sal][data-sal-duration="300"]{transition-duration:.3s}[data-sal][data-sal-duration="350"]{transition-duration:.35s}[data-sal][data-sal-duration="400"]{transition-duration:.4s}[data-sal][data-sal-duration="450"]{transition-duration:.45s}[data-sal][data-sal-duration="500"]{transition-duration:.5s}[data-sal][data-sal-duration="550"]{transition-duration:.55s}[data-sal][data-sal-duration="600"]{transition-duration:.6s}[data-sal][data-sal-duration="650"]{transition-duration:.65s}[data-sal][data-sal-duration="700"]{transition-duration:.7s}[data-sal][data-sal-duration="750"]{transition-duration:.75s}[data-sal][data-sal-duration="800"]{transition-duration:.8s}[data-sal][data-sal-duration="850"]{transition-duration:.85s}[data-sal][data-sal-duration="900"]{transition-duration:.9s}[data-sal][data-sal-duration="950"]{transition-duration:.95s}[data-sal][data-sal-duration="1000"]{transition-duration:1s}[data-sal][data-sal-duration="1050"]{transition-duration:1.05s}[data-sal][data-sal-duration="1100"]{transition-duration:1.1s}[data-sal][data-sal-duration="1150"]{transition-duration:1.15s}[data-sal][data-sal-duration="1200"]{transition-duration:1.2s}[data-sal][data-sal-duration="1250"]{transition-duration:1.25s}[data-sal][data-sal-duration="1300"]{transition-duration:1.3s}[data-sal][data-sal-duration="1350"]{transition-duration:1.35s}[data-sal][data-sal-duration="1400"]{transition-duration:1.4s}[data-sal][data-sal-duration="1450"]{transition-duration:1.45s}[data-sal][data-sal-duration="1500"]{transition-duration:1.5s}[data-sal][data-sal-duration="1550"]{transition-duration:1.55s}[data-sal][data-sal-duration="1600"]{transition-duration:1.6s}[data-sal][data-sal-duration="1650"]{transition-duration:1.65s}[data-sal][data-sal-duration="1700"]{transition-duration:1.7s}[data-sal][data-sal-duration="1750"]{transition-duration:1.75s}[data-sal][data-sal-duration="1800"]{transition-duration:1.8s}[data-sal][data-sal-duration="1850"]{transition-duration:1.85s}[data-sal][data-sal-duration="1900"]{transition-duration:1.9s}[data-sal][data-sal-duration="1950"]{transition-duration:1.95s}[data-sal][data-sal-duration="2000"]{transition-duration:2s}[data-sal][data-sal-delay="50"]{transition-delay:.05s}[data-sal][data-sal-delay="100"]{transition-delay:.1s}[data-sal][data-sal-delay="150"]{transition-delay:.15s}[data-sal][data-sal-delay="200"]{transition-delay:.2s}[data-sal][data-sal-delay="250"]{transition-delay:.25s}[data-sal][data-sal-delay="300"]{transition-delay:.3s}[data-sal][data-sal-delay="350"]{transition-delay:.35s}[data-sal][data-sal-delay="400"]{transition-delay:.4s}[data-sal][data-sal-delay="450"]{transition-delay:.45s}[data-sal][data-sal-delay="500"]{transition-delay:.5s}[data-sal][data-sal-delay="550"]{transition-delay:.55s}[data-sal][data-sal-delay="600"]{transition-delay:.6s}[data-sal][data-sal-delay="650"]{transition-delay:.65s}[data-sal][data-sal-delay="700"]{transition-delay:.7s}[data-sal][data-sal-delay="750"]{transition-delay:.75s}[data-sal][data-sal-delay="800"]{transition-delay:.8s}[data-sal][data-sal-delay="850"]{transition-delay:.85s}[data-sal][data-sal-delay="900"]{transition-delay:.9s}[data-sal][data-sal-delay="950"]{transition-delay:.95s}[data-sal][data-sal-delay="1000"]{transition-delay:1s}[data-sal][data-sal-easing=linear]{transition-timing-function:linear}[data-sal][data-sal-easing=ease]{transition-timing-function:ease}[data-sal][data-sal-easing=ease-in]{transition-timing-function:ease-in}[data-sal][data-sal-easing=ease-out]{transition-timing-function:ease-out}[data-sal][data-sal-easing=ease-in-out]{transition-timing-function:ease-in-out}[data-sal][data-sal-easing=ease-in-cubic]{transition-timing-function:cubic-bezier(.55,.055,.675,.19)}[data-sal][data-sal-easing=ease-out-cubic]{transition-timing-function:cubic-bezier(.215,.61,.355,1)}[data-sal][data-sal-easing=ease-in-out-cubic]{transition-timing-function:cubic-bezier(.645,.045,.355,1)}[data-sal][data-sal-easing=ease-in-circ]{transition-timing-function:cubic-bezier(.6,.04,.98,.335)}[data-sal][data-sal-easing=ease-out-circ]{transition-timing-function:cubic-bezier(.075,.82,.165,1)}[data-sal][data-sal-easing=ease-in-out-circ]{transition-timing-function:cubic-bezier(.785,.135,.15,.86)}[data-sal][data-sal-easing=ease-in-expo]{transition-timing-function:cubic-bezier(.95,.05,.795,.035)}[data-sal][data-sal-easing=ease-out-expo]{transition-timing-function:cubic-bezier(.19,1,.22,1)}[data-sal][data-sal-easing=ease-in-out-expo]{transition-timing-function:cubic-bezier(1,0,0,1)}[data-sal][data-sal-easing=ease-in-quad]{transition-timing-function:cubic-bezier(.55,.085,.68,.53)}[data-sal][data-sal-easing=ease-out-quad]{transition-timing-function:cubic-bezier(.25,.46,.45,.94)}[data-sal][data-sal-easing=ease-in-out-quad]{transition-timing-function:cubic-bezier(.455,.03,.515,.955)}[data-sal][data-sal-easing=ease-in-quart]{transition-timing-function:cubic-bezier(.895,.03,.685,.22)}[data-sal][data-sal-easing=ease-out-quart]{transition-timing-function:cubic-bezier(.165,.84,.44,1)}[data-sal][data-sal-easing=ease-in-out-quart]{transition-timing-function:cubic-bezier(.77,0,.175,1)}[data-sal][data-sal-easing=ease-in-quint]{transition-timing-function:cubic-bezier(.755,.05,.855,.06)}[data-sal][data-sal-easing=ease-out-quint]{transition-timing-function:cubic-bezier(.23,1,.32,1)}[data-sal][data-sal-easing=ease-in-out-quint]{transition-timing-function:cubic-bezier(.86,0,.07,1)}[data-sal][data-sal-easing=ease-in-sine]{transition-timing-function:cubic-bezier(.47,0,.745,.715)}[data-sal][data-sal-easing=ease-out-sine]{transition-timing-function:cubic-bezier(.39,.575,.565,1)}[data-sal][data-sal-easing=ease-in-out-sine]{transition-timing-function:cubic-bezier(.445,.05,.55,.95)}[data-sal][data-sal-easing=ease-in-back]{transition-timing-function:cubic-bezier(.6,-.28,.735,.045)}[data-sal][data-sal-easing=ease-out-back]{transition-timing-function:cubic-bezier(.175,.885,.32,1.275)}[data-sal][data-sal-easing=ease-in-out-back]{transition-timing-function:cubic-bezier(.68,-.55,.265,1.55)}[data-sal|=fade]{opacity:0;transition-property:opacity}[data-sal|=fade].sal-animate,body.sal-disabled [data-sal|=fade]{opacity:1}[data-sal|=slide]{opacity:0;transition-property:opacity,transform}[data-sal=slide-up]{transform:translateY(20%)}[data-sal=slide-down]{transform:translateY(-20%)}[data-sal=slide-left]{transform:translateX(20%)}[data-sal=slide-right]{transform:translateX(-20%)}[data-sal|=slide].sal-animate,body.sal-disabled [data-sal|=slide]{opacity:1;transform:none}[data-sal|=zoom]{opacity:0;transition-property:opacity,transform}[data-sal=zoom-in]{transform:scale(.5)}[data-sal=zoom-out]{transform:scale(1.1)}[data-sal|=zoom].sal-animate,body.sal-disabled [data-sal|=zoom]{opacity:1;transform:none}[data-sal|=flip]{-webkit-backface-visibility:hidden;backface-visibility:hidden;transition-property:transform}[data-sal=flip-left]{transform:perspective(2000px) rotateY(-91deg)}[data-sal=flip-right]{transform:perspective(2000px) rotateY(91deg)}[data-sal=flip-up]{transform:perspective(2000px) rotateX(-91deg)}[data-sal=flip-down]{transform:perspective(2000px) rotateX(91deg)}[data-sal|=flip].sal-animate,body.sal-disabled [data-sal|=flip]{transform:none}
2 |
3 | /*# sourceMappingURL=sal.css.map*/
--------------------------------------------------------------------------------
/dist/sal.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.sal=t():e.sal=t()}(this,(function(){return(()=>{"use strict";var e={d:(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function n(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function r(e){for(var t=1;tj});var a="Sal was not initialised! Probably it is used in SSR.",s="Your browser does not support IntersectionObserver!\nGet a polyfill from here:\nhttps://github.com/w3c/IntersectionObserver/tree/master/polyfill",i={root:null,rootMargin:"0% 50%",threshold:.5,animateClassName:"sal-animate",disabledClassName:"sal-disabled",enterEventName:"sal:in",exitEventName:"sal:out",selector:"[data-sal]",once:!0,disabled:!1},l=[],c=null,u=function(e){e&&e!==i&&(i=r(r({},i),e))},d=function(e){e.classList.remove(i.animateClassName)},f=function(e,t){var n=new CustomEvent(e,{bubbles:!0,detail:t});t.target.dispatchEvent(n)},b=function(){document.body.classList.add(i.disabledClassName)},p=function(){c.disconnect(),c=null},m=function(){return i.disabled||"function"==typeof i.disabled&&i.disabled()},v=function(e,t){e.forEach((function(e){var n=e.target,r=void 0!==n.dataset.salRepeat,o=void 0!==n.dataset.salOnce,a=r||!(o||i.once);e.intersectionRatio>=i.threshold?(function(e){e.target.classList.add(i.animateClassName),f(i.enterEventName,e)}(e),a||t.unobserve(n)):a&&function(e){d(e.target),f(i.exitEventName,e)}(e)}))},y=function(){var e=[].filter.call(document.querySelectorAll(i.selector),(function(e){return!function(e){return e.classList.contains(i.animateClassName)}(e,i.animateClassName)}));return e.forEach((function(e){return c.observe(e)})),e},O=function(){b(),p()},h=function(){document.body.classList.remove(i.disabledClassName),c=new IntersectionObserver(v,{root:i.root,rootMargin:i.rootMargin,threshold:i.threshold}),l=y()},g=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};p(),Array.from(document.querySelectorAll(i.selector)).forEach(d),u(e),h()},w=function(){var e=y();l.push(e)};const j=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:i;if(u(e),"undefined"==typeof window)return console.warn(a),{elements:l,disable:O,enable:h,reset:g,update:w};if(!window.IntersectionObserver)throw b(),Error(s);return m()?b():h(),{elements:l,disable:O,enable:h,reset:g,update:w}};return t.default})()}));
2 | //# sourceMappingURL=sal.js.map
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace sal {
2 | interface Options {
3 | root: Element | null;
4 | rootMargin?: string;
5 | threshold?: number;
6 | animateClassName?: string;
7 | disabledClassName?: string;
8 | enterEventName?: string,
9 | exitEventName?: string,
10 | selector?: string;
11 | once?: boolean;
12 | disabled?: boolean;
13 | }
14 |
15 | interface API {
16 | /**
17 | * Collection of elements to be animated.
18 | */
19 | elements: HTMLElement[];
20 |
21 | /**
22 | * Enables instance by launching new IntersectionObserver.
23 | */
24 | enable: () => void;
25 |
26 | /**
27 | * Disables instance by removing animations and clearing observer.
28 | */
29 | disable: () => void;
30 |
31 | /**
32 | * Resets instance to provide new settings.
33 | * @param {Options} settings
34 | */
35 | reset: (settings?: Options) => void;
36 |
37 | /**
38 | * Updates observer with new elements to animated.
39 | * Useful for dynamically injected elements.
40 | */
41 | update: () => void;
42 | }
43 |
44 | type Instance = (options?: Options) => API;
45 | }
46 |
47 | declare const sal: sal.Instance;
48 |
49 | export as namespace sal;
50 | export = sal;
51 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 | Sal - Lightweight scroll animation library