New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

affixing-header

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

affixing-header - npm Package Compare versions

Comparing version 1.0.0-beta.3 to 1.0.0-beta.4

8

dist/affixing-header.d.ts

@@ -1,3 +0,7 @@

export default function (navElement: HTMLElement, { useSticky }?: {
type Options = {
classNameAffixed?: string;
classNameAffixing?: string;
useSticky?: boolean;
}): () => void;
};
export default function (navElement: HTMLElement, options?: Options): () => void;
export {};

@@ -17,2 +17,4 @@ var _a;

let affixedPosition = 'fixed';
let classNameAffixed = null;
let classNameAffixing = null;
let header = null;

@@ -26,2 +28,8 @@ let headerDimensions = {};

isNavTransitioning = false;
if (classNameAffixed) {
header.classList.add(classNameAffixed);
}
if (classNameAffixing) {
header.classList.remove(classNameAffixing);
}
header.style.position = affixedPosition;

@@ -36,5 +44,11 @@ header.style.top = '0px';

}
let newHeaderTop = null;
upScrollCount = 0;
isNavAffixed = false;
if (classNameAffixed) {
header.classList.remove(classNameAffixed);
}
if (classNameAffixing) {
header.classList.remove(classNameAffixing);
}
let newHeaderTop = null;
// Only set top position for switch from fixed absolute if not transitioning

@@ -104,2 +118,5 @@ if (!isNavTransitioning) {

header.style.top = headerDimensions.top + 'px';
if (classNameAffixing) {
header.classList.add(classNameAffixing);
}
}

@@ -129,6 +146,12 @@ isNavTransitioning = true;

}
export default function (navElement, { useSticky } = {}) {
export default function (navElement, options = {}) {
// Set initial state
header = navElement;
affixedPosition = useSticky ? 'sticky' : 'fixed';
affixedPosition = options.useSticky ? 'sticky' : 'fixed';
if (options.classNameAffixed) {
classNameAffixed = options.classNameAffixed;
}
if (options.classNameAffixing) {
classNameAffixing = options.classNameAffixing;
}
const initialHeaderPosition = header.style.position;

@@ -151,4 +174,12 @@ const initialHeaderTop = header.style.top;

header.style.top = initialHeaderTop;
if (classNameAffixed) {
header.classList.remove(classNameAffixed);
}
if (classNameAffixing) {
header.classList.remove(classNameAffixing);
}
header = null;
}
affixedPosition = 'fixed';
classNameAffixed = classNameAffixing = null;
headerDimensions = documentDimensions = {};

@@ -155,0 +186,0 @@ scrollY = scrollYPrevious = upScrollCount = 0;

@@ -23,4 +23,3 @@ import { Window } from 'happy-dom';

const cleanup = affixingHeader(nav);
expect(nav.style.position).toBe('absolute');
expect(nav.style.top).toBe('0px');
expect(nav).toHaveStyle({ position: 'absolute', top: '0px' });
for (let index = 0; index < 5; index++) {

@@ -30,4 +29,3 @@ triggerScroll(20);

}
expect(nav.style.position).toBe('absolute');
expect(nav.style.top).toBe('0px');
expect(nav).toHaveStyle({ position: 'absolute', top: '0px' });
// trigger a “deliberate” scroll up

@@ -38,16 +36,13 @@ for (let index = 0; index < 8; index++) {

}
expect(nav.style.position).toBe('absolute');
expect(nav).toHaveStyle({ position: 'absolute' });
expect(parseInt(nav.style.top, 10)).toBeGreaterThan(30);
triggerScroll(-30);
await delay(0);
expect(nav.style.position).toBe('fixed');
expect(nav.style.top).toBe('0px');
expect(nav).toHaveStyle({ position: 'fixed', top: '0px' });
cleanup();
expect(nav.style.position).toBe('');
expect(nav.style.top).toBe('');
expect(nav).toHaveStyle({ position: '', top: '' });
});
it('uses position: sticky for affixed header if options.useSticky is passed as true', async () => {
const cleanup = affixingHeader(nav, { useSticky: true });
expect(nav.style.position).toBe('absolute');
expect(nav.style.top).toBe('0px');
expect(nav).toHaveStyle({ position: 'absolute', top: '0px' });
for (let index = 0; index < 5; index++) {

@@ -57,4 +52,3 @@ triggerScroll(20);

}
expect(nav.style.position).toBe('absolute');
expect(nav.style.top).toBe('0px');
expect(nav).toHaveStyle({ position: 'absolute', top: '0px' });
// trigger a “deliberate” scroll up

@@ -65,13 +59,47 @@ for (let index = 0; index < 8; index++) {

}
expect(nav.style.position).toBe('absolute');
expect(nav).toHaveStyle({ position: 'absolute' });
expect(parseInt(nav.style.top, 10)).toBeGreaterThan(30);
triggerScroll(-30);
await delay(0);
expect(nav.style.position).toBe('sticky');
expect(nav.style.top).toBe('0px');
expect(nav).toHaveStyle({ position: 'sticky', top: '0px' });
cleanup();
expect(nav.style.position).toBe('');
expect(nav.style.top).toBe('');
expect(nav).toHaveStyle({ position: '', top: '' });
});
it('adds classNames when affixing and affixed based on options.classNameAffixed and options.classNameAffixing', async () => {
const cleanup = affixingHeader(nav, {
classNameAffixed: 'affixed',
classNameAffixing: 'affixing',
});
expect(nav).not.toHaveClass('affixed');
expect(nav).not.toHaveClass('affixing');
for (let index = 0; index < 5; index++) {
triggerScroll(20);
await delay(0);
}
expect(nav).not.toHaveClass('affixed');
expect(nav).not.toHaveClass('affixing');
// trigger a “deliberate” scroll up
for (let index = 0; index < 8; index++) {
triggerScroll(-2);
await delay(0);
}
expect(nav).not.toHaveClass('affixed');
expect(nav).toHaveClass('affixing');
expect(nav).toHaveStyle({ position: 'absolute' });
expect(parseInt(nav.style.top, 10)).toBeGreaterThan(30);
triggerScroll(-30);
await delay(0);
expect(nav).toHaveClass('affixed');
expect(nav).not.toHaveClass('affixing');
expect(nav).toHaveStyle({ position: 'fixed', top: '0px' });
for (let index = 0; index < 5; index++) {
triggerScroll(20);
await delay(0);
}
expect(nav).not.toHaveClass('affixed');
expect(nav).not.toHaveClass('affixing');
cleanup();
expect(nav).toHaveStyle({ position: '', top: '' });
});
});
//# sourceMappingURL=affixing-header.test.js.map
{
"name": "affixing-header",
"version": "1.0.0-beta.3",
"version": "1.0.0-beta.4",
"description": "An affixing header that behaves normally as a user navigates down a page, but reveals itself naturally when a user scrolls or drags upwards. Inspired by iOS Safari, Medium, and others.",

@@ -10,5 +10,3 @@ "type": "module",

"types": "./dist/affixing-header.d.ts",
"files": [
"dist"
],
"files": ["dist"],
"scripts": {

@@ -15,0 +13,0 @@ "build": "npm run lint && tsc --build",

@@ -9,3 +9,3 @@ # Affixing Header&nbsp; [![build workflow](https://github.com/acusti/affixing-header/actions/workflows/deploy.yml/badge.svg)](https://github.com/acusti/affixing-header/actions)

### `affixingHeader( element )`
### `affixingHeader( element, options )`

@@ -16,2 +16,10 @@ #### `element` HTMLElement

#### `options` object `{ classNameAffixed?: string; classNameAffixing?: string; useSticky?: boolean }`
Optional options for customizing the behavior of the affixing header:
- `{ classNameAffixed: string }` will add the specified class to the header when it is affixed (i.e. when it has been scrolled up)
- `{ classNameAffixing: string }` will add the specified class to the header when it is in the process of affixing (i.e. when the user has started scrolling up and the header is moving into view)
- `{ useSticky: true }` will cause the module to use `position: sticky` (instead of `position: fixed`) when affixing the header on scrolling up
### affixingHeader return value

@@ -23,13 +31,20 @@

### Dependencies
## Dependencies
This package uses [onscrolling][], a requestAnimationFrame-based, performant, mobile-friendly scroll event handler, to listen for page scrolls, but has no other dependencies.
### Compatibility
## Compatibility
The scroll handling uses `requestAnimationFrame`, which is [only available in IE10+][raf-caniuse]. To add full support for older browsers, just include a [requestAnimationFrame polyfill][raf-polyfill].
This module is ESM-only and takes advantage of modern JS language features. It includes code to ensure it won’t throw errors in non-browser environments (e.g. node, workersd, deno, bun, etc.), where it will not do anything but also won’t break SSR. To make it compatible with non-ESM environments and older browsers, it must be transpiled.
## Tests
Tests use vitest + happy-dom and can be run with `yarn test`.
## TODO
- [ ] Add `{ scrollingParent: DOMElement }` option for usage with scrollable elements other than `scrollingDocument`
- [ ] Refactor nextTick approach to use an IntersectionObserver with a threshold of 99 to detect when the header should be affixed
[acusti.ca]: http://www.acusti.ca
[onscrolling]: https://github.com/acusti/onscrolling
[raf-caniuse]: http://caniuse.com/#feat=requestanimationframe
[raf-polyfill]: https://gist.github.com/paulirish/1579671

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