Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
77d21e1
Merge tag '3.0.4' into develop
titouanmathis May 12, 2025
cd5199f
Update dependency vitepress-plugin-llms to v1.1.4
renovate-bot May 15, 2025
c73e720
Merge pull request #632 from studiometa/renovate/docs-dev-dependencies
titouanmathis May 15, 2025
86a85de
Update dependency @types/node to v22.15.18
renovate-bot May 17, 2025
4b5f40e
Merge pull request #633 from studiometa/renovate/dev-dependencies
titouanmathis May 19, 2025
6473b36
Update dependency @shikijs/vitepress-twoslash to v3.4.2
renovate-bot May 19, 2025
0a22b74
Merge pull request #634 from studiometa/renovate/docs-dev-dependencies
titouanmathis May 19, 2025
41e4ee8
Update devDependencies
renovate-bot May 23, 2025
e6421b0
Merge pull request #635 from studiometa/renovate/dev-dependencies
titouanmathis May 26, 2025
8ea33dc
Update devDependencies
renovate-bot Jun 1, 2025
b9e34e1
Merge pull request #638 from studiometa/renovate/dev-dependencies
titouanmathis Jun 2, 2025
a7f5e29
Update docs devDependencies
renovate-bot Jun 9, 2025
4aa49cd
Update devDependencies
renovate-bot Jun 9, 2025
5dd4c2d
Merge pull request #639 from studiometa/renovate/dev-dependencies
titouanmathis Jun 9, 2025
189ba45
Merge pull request #637 from studiometa/renovate/docs-dev-dependencies
titouanmathis Jun 9, 2025
22543c7
Update demo devDependencies
renovate-bot Jun 8, 2025
5bb1276
Merge pull request #636 from studiometa/renovate/demo-dev-dependencies
titouanmathis Jun 9, 2025
844d3ad
Update devDependencies
renovate-bot Jun 13, 2025
fe7b21e
Merge pull request #641 from studiometa/renovate/dev-dependencies
titouanmathis Jun 16, 2025
0e0df83
Update devDependencies
renovate-bot Jul 4, 2025
157b8cc
Update demo devDependencies
renovate-bot Jul 6, 2025
5039361
Update docs devDependencies
renovate-bot Jul 9, 2025
158d0b6
Avoid layout thrashing for the scroll service
titouanmathis May 16, 2025
882afc4
Update @studiometa/ui in the demo
titouanmathis May 16, 2025
83b65f1
Improve performance
titouanmathis Jul 17, 2025
9ba59a1
Update tests
titouanmathis Jul 17, 2025
3eaf7d0
Update changelog
titouanmathis Jul 23, 2025
41844e7
Merge pull request #645 from studiometa/bugfix/scroll-layout-thrashing
titouanmathis Jul 23, 2025
6e01855
Fix scroll to be always instant
titouanmathis Jul 7, 2025
547f4f9
Add tests
titouanmathis Jul 7, 2025
4fe8d16
Update changelog
titouanmathis Jul 23, 2025
dc3bd18
Merge pull request #644 from studiometa/bugfix/scrollto
titouanmathis Jul 23, 2025
f92f02a
Merge pull request #640 from studiometa/renovate/docs-dev-dependencies
titouanmathis Jul 23, 2025
6b6b00c
Merge pull request #642 from studiometa/renovate/demo-dev-dependencies
titouanmathis Jul 23, 2025
208f187
Merge pull request #643 from studiometa/renovate/dev-dependencies
titouanmathis Jul 23, 2025
0631a45
Bump version number
titouanmathis Jul 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format

## [Unreleased]

## [v3.0.5](https://github.com/studiometa/js-toolkit/compare/3.0.4..3.0.5) (2025-07-23)

### Changed

- **withScrolledInView:** improve performance ([#645](https://github.com/studiometa/js-toolkit/pull/645), [83b65f16](https://github.com/studiometa/js-toolkit/commit/83b65f16))
- **useScroll:** avoid layout thrashing ([#645](https://github.com/studiometa/js-toolkit/pull/645), [158d0b66](https://github.com/studiometa/js-toolkit/commit/158d0b66))

### Fixed

- **scrollTo:** fix scroll to be always instant ([#644](https://github.com/studiometa/js-toolkit/pull/644), [6e018553](https://github.com/studiometa/js-toolkit/commit/6e018553))

## [v3.0.4](https://github.com/studiometa/js-toolkit/compare/3.0.3..3.0.4) (2025-05-12)

### Changed
Expand Down
5,535 changes: 1,962 additions & 3,573 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@studiometa/js-toolkit-workspace",
"version": "3.0.4",
"version": "3.0.5",
"private": true,
"type": "module",
"workspaces": [
Expand Down Expand Up @@ -30,10 +30,10 @@
"build-for-export-size": "node scripts/add-utils-export.js && rm -rf dist && npm run build:pkg && npm run build:cp-files"
},
"devDependencies": {
"@studiometa/prettier-config": "4.1.0",
"@types/node": "22.15.17",
"oxlint": "0.16.10",
"prettier": "3.5.3",
"@studiometa/prettier-config": "4.2.0",
"@types/node": "22.16.0",
"oxlint": "0.18.1",
"prettier": "3.6.2",
"typescript": "5.8.3"
},
"dependencies": {
Expand Down
20 changes: 10 additions & 10 deletions packages/demo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@studiometa/js-toolkit-demo",
"version": "3.0.4",
"version": "3.0.5",
"private": true,
"type": "module",
"scripts": {
Expand All @@ -19,20 +19,20 @@
"fix:prettier": "npm run lint:prettier -- --write"
},
"dependencies": {
"@studiometa/ui": "^1.0.0-beta.0",
"@studiometa/ui": "1.0.0-rc.2",
"tailwindcss": "^3.4.14"
},
"devDependencies": {
"@studiometa/eslint-config": "4.2.0",
"@studiometa/prettier-config": "4.1.0",
"@studiometa/stylelint-config": "4.0.0",
"@studiometa/eslint-config": "4.3.1",
"@studiometa/prettier-config": "4.2.0",
"@studiometa/stylelint-config": "4.1.1",
"@studiometa/tailwind-config": "2.1.0",
"@studiometa/webpack-config": "6.3.4",
"@studiometa/webpack-config-preset-prototyping": "6.3.4",
"eslint": "9.26.0",
"@studiometa/webpack-config": "6.3.6",
"@studiometa/webpack-config-preset-prototyping": "6.3.6",
"eslint": "9.30.1",
"http-server": "14.1.1",
"prettier": "3.5.3",
"stylelint": "16.19.1"
"prettier": "3.6.2",
"stylelint": "16.21.1"
},
"stylelint": {
"extends": "@studiometa/stylelint-config"
Expand Down
6 changes: 3 additions & 3 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@studiometa/js-toolkit-docs",
"version": "3.0.4",
"version": "3.0.5",
"type": "module",
"private": true,
"scripts": {
Expand All @@ -9,10 +9,10 @@
"preview": "vitepress preview ."
},
"devDependencies": {
"@shikijs/vitepress-twoslash": "3.4.0",
"@shikijs/vitepress-twoslash": "3.7.0",
"@studiometa/tailwind-config": "2.1.0",
"tailwindcss": "3.4.17",
"vitepress": "1.6.3",
"vitepress-plugin-llms": "1.1.3"
"vitepress-plugin-llms": "1.7.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
ScrollServiceProps,
ResizeServiceProps,
} from '../../services/index.js';
import { useScroll } from '../../services/index.js';
import { withMountWhenInView } from '../withMountWhenInView.js';
import {
damp,
Expand Down Expand Up @@ -78,11 +79,7 @@ function updateProps(
dampPrecision: number,
axis: 'x' | 'y' = 'x',
): void {
props.current[axis] = clamp(
axis === 'x' ? window.scrollX : window.scrollY,
props.start[axis],
props.end[axis],
);
props.current[axis] = clamp(useScroll().props()[axis], props.start[axis], props.end[axis]);
props.dampedCurrent[axis] = damp(
props.current[axis],
props.dampedCurrent[axis],
Expand Down
2 changes: 1 addition & 1 deletion packages/js-toolkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@studiometa/js-toolkit",
"version": "3.0.4",
"version": "3.0.5",
"description": "A set of useful little bits of JavaScript to boost your project! 🚀",
"publishConfig": {
"access": "public"
Expand Down
9 changes: 7 additions & 2 deletions packages/js-toolkit/services/ScrollService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ServiceConfig, ServiceInterface } from './AbstractService.js';
import { AbstractService } from './AbstractService.js';
import { debounce } from '../utils/debounce.js';
import { PASSIVE_CAPTURE_EVENT_OPTIONS } from './utils.js';
import { nextTick } from '../utils/nextTick.js';

export interface ScrollServiceProps {
x: number;
Expand Down Expand Up @@ -105,15 +106,19 @@ export class ScrollService extends AbstractService<ScrollServiceProps> {
return props;
}

update() {
nextTick(() => this.updateProps()).then(() => this.trigger(this.props));
}

onScrollDebounced = debounce(() => {
this.trigger(this.updateProps());
this.update();
}, 100);

/**
* Scroll handler.
*/
handleEvent() {
this.trigger(this.updateProps());
this.update();
this.onScrollDebounced();
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/js-toolkit/utils/scrollTo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ export function scrollTo(
rootElement.scrollTo({
left: lerp(initialScrollPosition.left, targetScrollPosition.left, progress),
top: lerp(initialScrollPosition.top, targetScrollPosition.top, progress),
behavior: 'instant',
});
},
{
Expand Down
2 changes: 1 addition & 1 deletion packages/tests/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@studiometa/js-toolkit-tests",
"version": "3.0.4",
"version": "3.0.5",
"private": true,
"type": "module",
"scripts": {
Expand Down
16 changes: 12 additions & 4 deletions packages/tests/services/ScrollService.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, it, expect, vi } from 'vitest';
import { useScroll } from '@studiometa/js-toolkit';
import { advanceTimersByTime, dispatch, useFakeTimers, useRealTimers } from '#test-utils';
import { wait } from '#private/utils';

describe('The `useScroll` service', () => {
it('should expose a single instance', () => {
Expand Down Expand Up @@ -57,31 +58,33 @@ describe('The `useScroll` service', () => {
`);
});

it('should trigger on scroll', () => {
it('should trigger on scroll', async () => {
const service = useScroll();
const fn = vi.fn();
service.add('key', fn);
dispatch(document, 'scroll');
await wait(1);
expect(fn).toHaveBeenLastCalledWith(service.props());
fn.mockRestore();
service.remove('key');
dispatch(document, 'scroll');
expect(fn).not.toHaveBeenCalled();
});

it('should trigger after debounce', () => {
it('should trigger after debounce', async () => {
const service = useScroll();
const fn = vi.fn();
service.add('key', fn);
useFakeTimers();
dispatch(document, 'scroll');
advanceTimersByTime(101);
useRealTimers();
await wait();
expect(fn).toHaveBeenCalledTimes(2);
service.remove('key');
});

it('should always have a progress of 1 if the page is not scrollable', () => {
it('should always have a progress of 1 if the page is not scrollable', async () => {
const spyWidth = vi.spyOn(document.scrollingElement, 'scrollWidth', 'get');
spyWidth.mockImplementation(() => window.innerWidth);
const spyHeight = vi.spyOn(document.scrollingElement, 'scrollHeight', 'get');
Expand All @@ -90,12 +93,13 @@ describe('The `useScroll` service', () => {
const fn = vi.fn();
service.add('key', fn);
dispatch(document, 'scroll');
await wait();
expect(service.props().maxX).toBe(0);
expect(service.props().maxY).toBe(0);
service.remove('key');
});

it('should update the direction accordingly', () => {
it('should update the direction accordingly', async () => {
const spyWidth = vi.spyOn(document.scrollingElement, 'scrollWidth', 'get');
spyWidth.mockImplementation(() => window.innerWidth * 2);
const spyHeight = vi.spyOn(document.scrollingElement, 'scrollHeight', 'get');
Expand All @@ -111,22 +115,26 @@ describe('The `useScroll` service', () => {
scrollXSpy.mockImplementation(() => 0);
scrollYSpy.mockImplementation(() => 0);
dispatch(document, 'scroll');
await wait();
expect(service.props().direction.x).toBe('NONE');
expect(service.props().direction.y).toBe('NONE');

scrollXSpy.mockImplementation(() => 10);
scrollYSpy.mockImplementation(() => 10);
dispatch(document, 'scroll');
await wait();
expect(service.props().direction.x).toBe('RIGHT');
expect(service.props().direction.y).toBe('DOWN');

scrollXSpy.mockImplementation(() => 0);
scrollYSpy.mockImplementation(() => 0);
dispatch(document, 'scroll');
await wait();
expect(service.props().direction.x).toBe('LEFT');
expect(service.props().direction.y).toBe('UP');

dispatch(document, 'scroll');
await wait();
expect(service.props().direction.x).toBe('NONE');
expect(service.props().direction.y).toBe('NONE');

Expand Down
Loading
Loading