Skip to content

Commit a4075d8

Browse files
committed
Release v3.0.0: Modernize with hooks, TypeScript, and additional improvements
- Finalize v3.0.0 release by updating version and dependencies. - Add Prettier for consistent code formatting, along with `.prettierignore` and `.prettierrc` configuration. - Enable stricter and more predictable test setups with fake timers and updated mocks. - Refactor and restore disabled tests for better coverage and reliability. - Update GitHub Actions workflow to support Node.js 22.x and v3 branch. - Enhance utility function and component formatting for clarity and maintainability.
1 parent 4451720 commit a4075d8

9 files changed

Lines changed: 138 additions & 91 deletions

File tree

.github/workflows/build-test.yml

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ on:
44
push:
55
branches:
66
- master
7+
- v3
78
pull_request:
89
branches:
910
- master
11+
- v3
1012

1113
jobs:
1214
build-test-v3:
@@ -20,20 +22,28 @@ jobs:
2022
- name: Use Node.js
2123
uses: actions/setup-node@v4
2224
with:
23-
node-version: 18.x
25+
node-version: 22.x
2426

2527
- name: Install v3 dependencies
2628
working-directory: ./v3
2729
run: npm ci
2830

29-
- name: Build v3
31+
- name: Typecheck v3
3032
working-directory: ./v3
31-
run: npm run build
33+
run: npm run typecheck
34+
35+
- name: Lint v3
36+
working-directory: ./v3
37+
run: npm run lint
3238

3339
- name: Run v3 tests
3440
working-directory: ./v3
3541
run: npm test
3642

43+
- name: Build v3
44+
working-directory: ./v3
45+
run: npm run build
46+
3747
build-test-legacy:
3848
name: Build and Test Legacy (v0.1.x)
3949
runs-on: ubuntu-latest
@@ -46,7 +56,7 @@ jobs:
4656
- name: Use Node.js
4757
uses: actions/setup-node@v4
4858
with:
49-
node-version: 14.x
59+
node-version: 18.x
5060

5161
- name: Install dependencies
5262
uses: bahmutov/npm-install@v1
@@ -56,4 +66,3 @@ jobs:
5666

5767
- name: Test
5868
run: yarn test
59-
# run: yarn test:coverage

v3/.prettierignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
dist
2+
node_modules
3+
package-lock.json

v3/.prettierrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"tabWidth": 2,
5+
"trailingComma": "es5",
6+
"printWidth": 80,
7+
"arrowParens": "always"
8+
}

v3/package-lock.json

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

v3/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-split-pane",
3-
"version": "3.0.0-alpha.1",
3+
"version": "3.0.0",
44
"description": "React split-pane component - v3 modernized with hooks and TypeScript",
55
"type": "module",
66
"main": "./dist/index.cjs",
@@ -35,6 +35,8 @@
3535
"test:watch": "vitest",
3636
"test:coverage": "vitest run --coverage",
3737
"lint": "eslint src",
38+
"format": "prettier --write src",
39+
"format:check": "prettier --check src",
3840
"typecheck": "tsc --noEmit",
3941
"prepublishOnly": "npm run test && npm run build"
4042
},
@@ -77,6 +79,7 @@
7779
"eslint": "^9.39.2",
7880
"globals": "^16.2.0",
7981
"jsdom": "^26.1.0",
82+
"prettier": "^3.7.4",
8083
"react": "^18.3.1",
8184
"react-dom": "^18.3.1",
8285
"rollup": "^4.54.0",
Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,43 @@
1-
import { describe, it, expect } from 'vitest';
1+
import { describe, it, expect, vi } from 'vitest';
22
import { render, screen, act } from '@testing-library/react';
3-
import type { RenderResult } from '@testing-library/react';
43
import { SplitPane } from './SplitPane';
54
import { Pane } from './Pane';
65

76
describe('SplitPane', () => {
8-
// TODO: Fix ResizeObserver mock timing for these tests
9-
// These tests work in real browsers but have timing issues in test environment
10-
// Core functionality is verified by utility tests
11-
it.skip('renders children panes', async () => {
7+
it('renders children panes', async () => {
8+
render(
9+
<SplitPane>
10+
<Pane>
11+
<div>Pane 1</div>
12+
</Pane>
13+
<Pane>
14+
<div>Pane 2</div>
15+
</Pane>
16+
</SplitPane>
17+
);
18+
19+
// Flush state updates from ResizeObserver callback
1220
await act(async () => {
13-
render(
14-
<SplitPane>
15-
<Pane>
16-
<div>Pane 1</div>
17-
</Pane>
18-
<Pane>
19-
<div>Pane 2</div>
20-
</Pane>
21-
</SplitPane>
22-
);
23-
// Give ResizeObserver time to fire
24-
await new Promise((resolve) => setTimeout(resolve, 10));
21+
await vi.runAllTimersAsync();
2522
});
2623

2724
expect(screen.getByText('Pane 1')).toBeInTheDocument();
2825
expect(screen.getByText('Pane 2')).toBeInTheDocument();
2926
});
3027

31-
it.skip('renders divider between panes', async () => {
32-
let component: RenderResult | undefined;
28+
it('renders divider between panes', async () => {
29+
const { container } = render(
30+
<SplitPane>
31+
<Pane>Pane 1</Pane>
32+
<Pane>Pane 2</Pane>
33+
</SplitPane>
34+
);
3335

3436
await act(async () => {
35-
component = render(
36-
<SplitPane>
37-
<Pane>Pane 1</Pane>
38-
<Pane>Pane 2</Pane>
39-
</SplitPane>
40-
);
41-
await new Promise((resolve) => setTimeout(resolve, 10));
37+
await vi.runAllTimersAsync();
4238
});
4339

44-
const divider = component?.container.querySelector('[role="separator"]');
40+
const divider = container.querySelector('[role="separator"]');
4541
expect(divider).toBeInTheDocument();
4642
});
4743

@@ -81,23 +77,20 @@ describe('SplitPane', () => {
8177
expect(splitPane).toHaveClass('custom-class');
8278
});
8379

84-
it.skip('renders correct number of dividers for multiple panes', async () => {
85-
let component: RenderResult | undefined;
80+
it('renders correct number of dividers for multiple panes', async () => {
81+
const { container } = render(
82+
<SplitPane>
83+
<Pane>Pane 1</Pane>
84+
<Pane>Pane 2</Pane>
85+
<Pane>Pane 3</Pane>
86+
</SplitPane>
87+
);
8688

8789
await act(async () => {
88-
component = render(
89-
<SplitPane>
90-
<Pane>Pane 1</Pane>
91-
<Pane>Pane 2</Pane>
92-
<Pane>Pane 3</Pane>
93-
</SplitPane>
94-
);
95-
await new Promise((resolve) => setTimeout(resolve, 10));
90+
await vi.runAllTimersAsync();
9691
});
9792

98-
const dividers = component?.container.querySelectorAll(
99-
'[role="separator"]'
100-
);
93+
const dividers = container.querySelectorAll('[role="separator"]');
10194
expect(dividers).toHaveLength(2); // n-1 dividers for n panes
10295
});
10396
});

v3/src/test/setup.ts

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,21 @@
11
import '@testing-library/jest-dom';
2+
import { vi } from 'vitest';
3+
4+
// Use fake timers globally
5+
vi.useFakeTimers();
6+
7+
// Mock getBoundingClientRect to return proper dimensions
8+
Element.prototype.getBoundingClientRect = vi.fn(() => ({
9+
width: 1024,
10+
height: 768,
11+
top: 0,
12+
left: 0,
13+
bottom: 768,
14+
right: 1024,
15+
x: 0,
16+
y: 0,
17+
toJSON: () => ({}),
18+
}));
219

320
// Mock ResizeObserver with callback support
421
((globalThis as unknown) as {
@@ -11,29 +28,27 @@ import '@testing-library/jest-dom';
1128
}
1229

1330
observe(target: Element) {
14-
// Call callback async to simulate real ResizeObserver behavior
15-
setTimeout(() => {
16-
const mockEntry = ({
17-
target,
18-
contentRect: {
19-
width: 1024,
20-
height: 768,
21-
top: 0,
22-
left: 0,
23-
bottom: 768,
24-
right: 1024,
25-
x: 0,
26-
y: 0,
27-
toJSON: () => ({}),
28-
},
29-
borderBoxSize: [],
30-
contentBoxSize: [],
31-
devicePixelContentBoxSize: [],
32-
} as unknown) as ResizeObserverEntry;
33-
34-
// Call callback with mock data
35-
this.callback([mockEntry], this);
36-
}, 0);
31+
// Call callback synchronously for predictable testing
32+
const mockEntry = ({
33+
target,
34+
contentRect: {
35+
width: 1024,
36+
height: 768,
37+
top: 0,
38+
left: 0,
39+
bottom: 768,
40+
right: 1024,
41+
x: 0,
42+
y: 0,
43+
toJSON: () => ({}),
44+
},
45+
borderBoxSize: [],
46+
contentBoxSize: [],
47+
devicePixelContentBoxSize: [],
48+
} as unknown) as ResizeObserverEntry;
49+
50+
// Call callback synchronously
51+
this.callback([mockEntry], this);
3752
}
3853

3954
unobserve() {
@@ -44,16 +59,3 @@ import '@testing-library/jest-dom';
4459
// Mock implementation
4560
}
4661
};
47-
48-
// Mock requestAnimationFrame
49-
((globalThis as unknown) as {
50-
requestAnimationFrame: typeof requestAnimationFrame;
51-
}).requestAnimationFrame = (callback: FrameRequestCallback) => {
52-
return (setTimeout(callback, 0) as unknown) as number;
53-
};
54-
55-
((globalThis as unknown) as {
56-
cancelAnimationFrame: typeof cancelAnimationFrame;
57-
}).cancelAnimationFrame = (id: number) => {
58-
clearTimeout(id);
59-
};

v3/src/utils/accessibility.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
/**
22
* Announce a message to screen readers
33
*/
4-
export function announce(message: string, priority: 'polite' | 'assertive' = 'polite'): void {
4+
export function announce(
5+
message: string,
6+
priority: 'polite' | 'assertive' = 'polite'
7+
): void {
58
const announcement = document.createElement('div');
69
announcement.setAttribute('role', 'status');
710
announcement.setAttribute('aria-live', priority);
@@ -45,10 +48,13 @@ export function getDividerLabel(
4548
/**
4649
* Get keyboard instructions for divider
4750
*/
48-
export function getKeyboardInstructions(direction: 'horizontal' | 'vertical'): string {
49-
const keys = direction === 'horizontal'
50-
? 'left and right arrow keys'
51-
: 'up and down arrow keys';
51+
export function getKeyboardInstructions(
52+
direction: 'horizontal' | 'vertical'
53+
): string {
54+
const keys =
55+
direction === 'horizontal'
56+
? 'left and right arrow keys'
57+
: 'up and down arrow keys';
5258

5359
return `Use ${keys} to resize. Hold Shift for larger steps. Press Home or End to minimize or maximize.`;
5460
}

v3/src/utils/calculations.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,13 @@ describe('calculateDraggedSizes', () => {
7878

7979
it('respects minimum constraints', () => {
8080
const sizes = [300, 700];
81-
const result = calculateDraggedSizes(sizes, 0, -250, [100, 100], [500, 900]);
81+
const result = calculateDraggedSizes(
82+
sizes,
83+
0,
84+
-250,
85+
[100, 100],
86+
[500, 900]
87+
);
8288

8389
expect(result[0]).toBe(100); // Cannot go below min
8490
expect(result[1]).toBe(900);

0 commit comments

Comments
 (0)