Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@svelte-plugins/viewable

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@svelte-plugins/viewable - npm Package Compare versions

Comparing version 0.1.3 to 1.0.0

10

CHANGELOG.md

@@ -8,4 +8,14 @@ # Changelog

## [1.0.0](https://github.com/svelte-plugins/svelte-viewable/releases/tag/v1.0.0) - 2021-04-02
- Interface changes that include exposing observer props and events
- Includes new `on:complete` event
- Replaced `enableObstructionDetection` with `detectObstructions`
## [0.1.3](https://github.com/svelte-plugins/svelte-viewable/releases/tag/v0.1.3) - 2021-04-01
- Enable SSR support
## [0.1.0](https://github.com/svelte-plugins/svelte-viewable/releases/tag/v0.1.0) - 2021-03-29
- Initial release

2

lib/index.js

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self)["@svelte-plugins/viewable"]=t()}(this,(function(){"use strict";function e(e){return e()}function t(t){t.forEach(e)}let n;function o(e){n=e}function i(){if(!n)throw new Error("Function called outside component initialization");return n}const r=[],l=[],c=[],d=[],s=Promise.resolve();let a=!1;function u(){return a||(a=!0,s.then(p)),s}function h(e){c.push(e)}let f=!1;const g=new Set;function p(){if(!f){f=!0;do{for(let e=0;e<r.length;e+=1){const t=r[e];o(t),v(t.$$)}for(o(null),r.length=0;l.length;)l.pop()();for(let e=0;e<c.length;e+=1){const t=c[e];g.has(t)||(g.add(t),t())}c.length=0}while(r.length);for(;d.length;)d.pop()();a=!1,f=!1,g.clear()}}function v(e){if(null!==e.fragment){e.update(),t(e.before_update);const n=e.dirty;e.dirty=[-1],e.fragment&&e.fragment.p(e.ctx,n),e.after_update.forEach(h)}}let b;return function(e){function i(t,i,r,l){const c=n;o({$$:{on_destroy:b,context:new Map(c?c.$$.context:[]),on_mount:[],before_update:[],after_update:[],callbacks:Object.create(null)}});const d=e(t,i,r,l);return o(c),d}return{render:(e={},n={})=>{b=[];const o={title:"",head:"",css:new Set},r=i(o,e,{},n);return t(b),{html:r,css:{code:Array.from(o.css).map((e=>e.code)).join("\n"),map:null},head:o.title+o.head}},$$render:i}}(((e,t,n,o)=>{let{element:r}=t,{rules:l}=t,{debug:c=!1}=t,{duration:d=0}=t,{percent:s=0}=t,{percentX:a=0}=t,{percentY:h=0}=t,{intervalRate:f=200}=t,{gridSize:g=20}=t,{enableObstructionDetection:p=!1}=t,v=null,b=null;const m=[],w=(...e)=>c&&console.log(...e),y=(e,t)=>{const n=(e=>{const t=g+1,n=Math.floor(e.width/t),o=Math.floor(e.height/t),i=Math.max(0,e.left),r=e.top,l=[];for(let e=1;e<t;e++){const c=i+n*e;for(let e=1;e<t;e++){const t=r+o*e;l[l.length]=[c,t]}}return l})(e);let o=0;for(let e=0,t=n.length;e<t;e++){const t=n[e][0],i=n[e][1],l=document.elementFromPoint(t,i);l===r||r.contains(l)||o++}const i=100*t,l=100-o/n.length*100,c=l<i;return c&&(s=l.toFixed(0)),c},$=e=>{const t=(()=>{const e=document.body,t=document.documentElement;return{height:window.innerHeight||t.clientHeight||e&&e.clientHeight,width:window.innerWidth||t.clientWidth||e&&e.clientWidth}})(),n=r.getBoundingClientRect(),o=Math.max(0,Math.min(n.bottom,t.height)-Math.max(n.top,0)),i=Math.max(0,Math.min(n.right,t.width)-Math.max(n.left,0)),l=o/(n.height||r.offsetHeight)||0,c=i/(n.width||r.offsetWidth)||0,d=Math.max(0,l+c-1);return a=(100*c).toFixed(0),h=(100*l).toFixed(0),s=(100*d).toFixed(0),p&&y(n,e)?0:d},x=()=>{const e=m.length;for(let t=0;t<e;t++){const e=m[t];if(e)if($(e.threshold)<e.threshold)e.history=null;else if(e.history||(d=0,e.history=Date.now()),d=(Date.now()-e.history)/1e3,w(`[ Tracking - ${d} - ${e.rule}]`),d>=e.duration&&(e.observer&&e.observer.unobserve(r),e.callback(e),e.history=Date.now(),m.splice(t,1),t-=1,w(m),!m.length)){w(`[ Finished - ${e.history} ]`),b&&(clearInterval(b),b=null);break}}},M=e=>{const t=t=>{const n=t[0];n.isIntersecting?n.isIntersecting&&!b&&(b=setInterval(x,f),x()):e.history=null};if(!e.observer){const n=new IntersectionObserver(t,{threshold:[0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]});n.observe(r),e.observer=n}};var _;return _=async()=>{await u(),null===r||v||((()=>{for(let e in l){const t=l[e],{duration:n=0,percentage:o=0,fn:i,...r}=t,c={...r,percentage:o,threshold:o/100,duration:n,callback:function(e){i(e),w("[ Viewable Rule ]\n"+JSON.stringify({...e},null,2))},rule:e,history:null};m.push(c),M(c)}})(),v=!0)},i().$$.after_update.push(_),function(e){i().$$.on_destroy.push(e)}((()=>{m.forEach((e=>{e.observer&&e.observer.disconnect()}))})),void 0===t.element&&n.element&&void 0!==r&&n.element(r),void 0===t.rules&&n.rules&&void 0!==l&&n.rules(l),void 0===t.debug&&n.debug&&void 0!==c&&n.debug(c),void 0===t.duration&&n.duration&&void 0!==d&&n.duration(d),void 0===t.percent&&n.percent&&void 0!==s&&n.percent(s),void 0===t.percentX&&n.percentX&&void 0!==a&&n.percentX(a),void 0===t.percentY&&n.percentY&&void 0!==h&&n.percentY(h),void 0===t.intervalRate&&n.intervalRate&&void 0!==f&&n.intervalRate(f),void 0===t.gridSize&&n.gridSize&&void 0!==g&&n.gridSize(g),void 0===t.enableObstructionDetection&&n.enableObstructionDetection&&void 0!==p&&n.enableObstructionDetection(p),`${o.default?o.default({}):""}`}))}));
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self)["@svelte-plugins/viewable"]=t()}(this,(function(){"use strict";function e(e){return e()}function t(t){t.forEach(e)}let n;function o(e){n=e}function r(){if(!n)throw new Error("Function called outside component initialization");return n}function i(){const e=r();return(t,n)=>{const o=e.$$.callbacks[t];if(o){const r=function(e,t){const n=document.createEvent("CustomEvent");return n.initCustomEvent(e,!1,!1,t),n}(t,n);o.slice().forEach((t=>{t.call(e,r)}))}}}const l=[],c=[],s=[],d=[],u=Promise.resolve();let a=!1;function h(){return a||(a=!0,u.then(p)),u}function f(e){s.push(e)}let g=!1;const v=new Set;function p(){if(!g){g=!0;do{for(let e=0;e<l.length;e+=1){const t=l[e];o(t),m(t.$$)}for(o(null),l.length=0;c.length;)c.pop()();for(let e=0;e<s.length;e+=1){const t=s[e];v.has(t)||(v.add(t),t())}s.length=0}while(l.length);for(;d.length;)d.pop()();a=!1,g=!1,v.clear()}}function m(e){if(null!==e.fragment){e.update(),t(e.before_update);const n=e.dirty;e.dirty=[-1],e.fragment&&e.fragment.p(e.ctx,n),e.after_update.forEach(f)}}let b;return function(e){function r(t,r,i,l){const c=n;o({$$:{on_destroy:b,context:new Map(c?c.$$.context:[]),on_mount:[],before_update:[],after_update:[],callbacks:Object.create(null)}});const s=e(t,r,i,l);return o(c),s}return{render:(e={},n={})=>{b=[];const o={title:"",head:"",css:new Set},i=r(o,e,{},n);return t(b),{html:i,css:{code:Array.from(o.css).map((e=>e.code)).join("\n"),map:null},head:o.title+o.head}},$$render:r}}(((e,t,n,o)=>{let{element:l}=t,{rules:c}=t,{debug:s=!1}=t,{duration:d=0}=t,{percent:u=0}=t,{percentX:a=0}=t,{percentY:f=0}=t,{intervalRate:g=200}=t,{gridSize:v=20}=t,{detectObstructions:p=!1}=t,{root:m=null}=t,{rootMargin:b="0px"}=t,{threshold:y=[0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1]}=t,{entry:w=null}=t,{intersecting:$=!1}=t,{observer:x=null}=t,M=null,E=null;const _=i(),F=[],I=(...e)=>s&&console.log(...e),O=(e,t)=>{const n=(e=>{const t=v+1,n=Math.floor(e.width/t),o=Math.floor(e.height/t),r=Math.max(0,e.left),i=e.top,l=[];for(let e=1;e<t;e++){const c=r+n*e;for(let e=1;e<t;e++){const t=i+o*e;l[l.length]=[c,t]}}return l})(e);let o=0;for(let e=0,t=n.length;e<t;e++){const t=n[e][0],r=n[e][1],i=document.elementFromPoint(t,r);i===l||l.contains(i)||o++}const r=100*t,i=100-o/n.length*100,c=i<r;return c&&(u=i.toFixed(0)),c},S=e=>{const t=(()=>{const e=document.body,t=document.documentElement;return{height:window.innerHeight||t.clientHeight||e&&e.clientHeight,width:window.innerWidth||t.clientWidth||e&&e.clientWidth}})(),n=l.getBoundingClientRect(),o=Math.max(0,Math.min(n.bottom,t.height)-Math.max(n.top,0)),r=Math.max(0,Math.min(n.right,t.width)-Math.max(n.left,0)),i=o/(n.height||l.offsetHeight)||0,c=r/(n.width||l.offsetWidth)||0,s=Math.max(0,i+c-1);return a=(100*c).toFixed(0),f=(100*i).toFixed(0),u=(100*s).toFixed(0),p&&O(n,e)?0:s},k=()=>{const e=F.length;for(let t=0;t<e;t++){const e=F[t];if(e)if(S(e.threshold)<e.threshold)e.history=null;else if(e.history||(d=0,e.history=Date.now()),d=(Date.now()-e.history)/1e3,I(`[ Tracking - ${d} - ${e.rule}]`),d>=e.duration&&(e.callback(e),e.history=Date.now(),e.repeat||(F.splice(t,1),t-=1),I(F),!F.length)){I(`[ Finished - ${e.history} ]`),_("complete",c),x&&(x.unobserve(l),x.disconnect()),E&&(clearInterval(E),E=null);break}}},R=e=>{x||(x=new IntersectionObserver((t=>{w=t[0],$=w.isIntersecting,w.isIntersecting?w.isIntersecting&&!E&&(E=setInterval(k,g),k()):e.history=null}),{root:m,rootMargin:b,threshold:y}),x.observe(l))};var z;return z=async()=>{null!==w&&(_("observe",w),w.isIntersecting&&_("intersect",w)),await h(),null===l||M||((()=>{for(let e in c){const t=c[e],{duration:n=0,percentage:o=0,fn:r,...i}=t,l={...i,percentage:o,threshold:o/100,duration:n,callback:function(e){r(e),I("[ Viewable Rule ]\n"+JSON.stringify({...e},null,2))},rule:e,history:null};F.push(l),R(l)}})(),M=!0)},r().$$.after_update.push(z),function(e){r().$$.on_destroy.push(e)}((()=>x&&x.disconnect())),void 0===t.element&&n.element&&void 0!==l&&n.element(l),void 0===t.rules&&n.rules&&void 0!==c&&n.rules(c),void 0===t.debug&&n.debug&&void 0!==s&&n.debug(s),void 0===t.duration&&n.duration&&void 0!==d&&n.duration(d),void 0===t.percent&&n.percent&&void 0!==u&&n.percent(u),void 0===t.percentX&&n.percentX&&void 0!==a&&n.percentX(a),void 0===t.percentY&&n.percentY&&void 0!==f&&n.percentY(f),void 0===t.intervalRate&&n.intervalRate&&void 0!==g&&n.intervalRate(g),void 0===t.gridSize&&n.gridSize&&void 0!==v&&n.gridSize(v),void 0===t.detectObstructions&&n.detectObstructions&&void 0!==p&&n.detectObstructions(p),void 0===t.root&&n.root&&void 0!==m&&n.root(m),void 0===t.rootMargin&&n.rootMargin&&void 0!==b&&n.rootMargin(b),void 0===t.threshold&&n.threshold&&void 0!==y&&n.threshold(y),void 0===t.entry&&n.entry&&void 0!==w&&n.entry(w),void 0===t.intersecting&&n.intersecting&&void 0!==$&&n.intersecting($),void 0===t.observer&&n.observer&&void 0!==x&&n.observer(x),`${o.default?o.default({duration:d,entry:w,intersecting:$,observer:x,percent:u,percentX:a,percentY:f}):""}`}))}));
{
"name": "@svelte-plugins/viewable",
"version": "0.1.3",
"version": "1.0.0",
"license": "MIT",

@@ -5,0 +5,0 @@ "description": "A simple rule-based approach to tracking element viewability.",

@@ -48,2 +48,60 @@ [![Run unit tests](https://github.com/svelte-plugins/viewable/actions/workflows/run-unit.yml/badge.svg)](https://github.com/svelte-plugins/viewable/actions/workflows/run-unit.yml)

Try the basic example in [Svelte REPL](https://svelte.dev/repl/c811481b8e1b48e9bed0f6ff7d1fa9c2).
## API
### Props
| Prop name | Description | Value |
| :----------- | :---------------------------------------------------------------- | :---------------------------------------------------------------------------------------------- |
| element | Element to observe | `HTMLElement` |
| rules | Viewability rules | `object` (default: `null`) |
| intervalRate | Rate to check measurement while intersecting (ms) | `number` (default: `200`) |
| gridSize | Size of the obstruction grid | `number` (default: `20`) |
| detectObstructions | If `true`, obstructions impacting the element will affect measurement | 'boolean' (default: `false`) |
| root | Containing element | `null` or `HTMLElement` (default: `null`) |
| rootMargin | Margin offset of the containing element | `string` (default: `"0px"`) |
| intersecting | `true` if the observed element is intersecting | `boolean` (default: `false`) |
| observer | IntersectionObserver instance | [`IntersectionObserver`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver) |
| entry | Observed element metadata | [`IntersectionObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry) |
| debug | If `true`, debug ouput will be logged to console | `boolean` (default: `false`) |
#### rules
| Prop name | Description | Value |
| :----------- | :------------------------------------------------------------------ | :---------------------------------- |
| duration | Consecutive time (seconds) that the element must be in view | `number` (default: `0`) |
| percentage | Percentage of the element that must be viewable | `number` (default: `0`) |
| repeat | If `true`, the rule will be applied indefinitely v once | `function` (default: `null`) |
| fn | Callback function to execute when rule has been met | `function` (default: `null`) |
```js
const rules = {
dwell: {
duration: 1,
percentage: 50,
fn: () => {
console.log('50% of the element was visible for at least 1 consecutive second.');
}
}
}
```
### Debug props
The properties below can be used to assist with debugging any issues you might have (ex: `bind:duration`, `bind:percent`, etc.)
| Prop name | Description | Value |
| :----------- | :---------------------------------------------------------------- | :---------------------- |
| duration | Viewable duration of the tracked element | `number` (default: `0`) |
| percent | Percentage of total viewable area (X+Y) | `number` (default: `0`) |
| percentX | Percentage of horizontal viewable area | `number` (default: `0`) |
| percentY | Percentage of vertical viewable area | `number` (default: `0`) |
### Events
- **on:observe**: Fired when an intersection change occurs (type `IntersectionObserverEntry`)
- **on:intersect**: Fired when an intersection change occurs and the element is intersecting (type `IntersectionObserverEntry`)
- **on:complete**: Fired when all rules have been executed
## Changelog

@@ -50,0 +108,0 @@

@@ -57,3 +57,3 @@ import { render } from '@testing-library/svelte';

await TestHarness({ debug: true, enableObstructionDetection: true, rules: { immediate: { fn: mock } } });
await TestHarness({ debug: true, detectObstructions: true, rules: { immediate: { fn: mock } } });

@@ -75,3 +75,3 @@ onIntersectionMock([{ isIntersecting: true }]);

const { container } = await TestHarness({
enableObstructionDetection: true,
detectObstructions: true,
rules: {

@@ -78,0 +78,0 @@ fifty4six: {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc