Skip to content

Commit 4033c19

Browse files
authored
feat: expose pointerType in ResizeEvent (#880)
feat: expose pointerType in ResizeEvent (#880) - Add pointerType field to ResizeEvent ('mouse' | 'touch' | 'pen') - Pass pointerType through onResizeStart, onResize, and onResizeEnd callbacks - Allows consumers to differentiate between input types Suggested by @delijah in #878
1 parent 6cf8d8b commit 4033c19

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

src/hooks/useResizer.test.ts

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ function createMockElement(): HTMLDivElement {
1414
// Helper to create a PointerEvent with required properties
1515
function createPointerEvent(
1616
type: string,
17-
options: { clientX?: number; clientY?: number; pointerId?: number } = {}
17+
options: {
18+
clientX?: number;
19+
clientY?: number;
20+
pointerId?: number;
21+
pointerType?: string;
22+
} = {}
1823
): PointerEvent {
1924
return new PointerEvent(type, {
2025
clientX: options.clientX ?? 0,
2126
clientY: options.clientY ?? 0,
2227
pointerId: options.pointerId ?? 1,
28+
pointerType: options.pointerType ?? 'mouse',
2329
bubbles: true,
2430
});
2531
}
@@ -160,6 +166,7 @@ describe('useResizer', () => {
160166
expect(onResizeStart).toHaveBeenCalledWith({
161167
sizes: [300, 700],
162168
source: 'pointer',
169+
pointerType: 'mouse',
163170
originalEvent: expect.any(PointerEvent),
164171
});
165172
});
@@ -284,6 +291,7 @@ describe('useResizer', () => {
284291
expect(onResizeEnd).toHaveBeenCalledWith([300, 700], {
285292
sizes: [300, 700],
286293
source: 'pointer',
294+
pointerType: 'mouse',
287295
});
288296
});
289297

@@ -590,7 +598,7 @@ describe('useResizer', () => {
590598
expect(mockElement.setPointerCapture).toHaveBeenCalledWith(42);
591599
});
592600

593-
it('handles touch input via pointer events', () => {
601+
it('handles touch input via pointer events and passes pointerType', () => {
594602
const mockElement = createMockElement();
595603
const onResizeStart = vi.fn();
596604
const { result } = renderHook(() =>
@@ -619,18 +627,21 @@ describe('useResizer', () => {
619627
expect(onResizeStart).toHaveBeenCalledWith({
620628
sizes: [300, 700],
621629
source: 'pointer',
630+
pointerType: 'touch',
622631
originalEvent: expect.any(PointerEvent),
623632
});
624633
});
625634

626-
it('handles pen input via pointer events', () => {
635+
it('handles pen input via pointer events and passes pointerType', () => {
627636
const mockElement = createMockElement();
637+
const onResizeStart = vi.fn();
628638
const { result } = renderHook(() =>
629639
useResizer({
630640
direction: 'horizontal',
631641
sizes: [300, 700],
632642
minSizes: [100, 100],
633643
maxSizes: [500, 900],
644+
onResizeStart,
634645
})
635646
);
636647

@@ -647,6 +658,44 @@ describe('useResizer', () => {
647658
});
648659

649660
expect(result.current.isDragging).toBe(true);
661+
expect(onResizeStart).toHaveBeenCalledWith({
662+
sizes: [300, 700],
663+
source: 'pointer',
664+
pointerType: 'pen',
665+
originalEvent: expect.any(PointerEvent),
666+
});
667+
});
668+
669+
it('passes mouse pointerType by default', () => {
670+
const mockElement = createMockElement();
671+
const onResizeStart = vi.fn();
672+
const { result } = renderHook(() =>
673+
useResizer({
674+
direction: 'horizontal',
675+
sizes: [300, 700],
676+
minSizes: [100, 100],
677+
maxSizes: [500, 900],
678+
onResizeStart,
679+
})
680+
);
681+
682+
act(() => {
683+
const pointerDown = result.current.handlePointerDown(0);
684+
const event = createMockReactPointerEvent(mockElement, {
685+
clientX: 300,
686+
clientY: 0,
687+
pointerId: 1,
688+
pointerType: 'mouse',
689+
});
690+
pointerDown(event);
691+
});
692+
693+
expect(onResizeStart).toHaveBeenCalledWith({
694+
sizes: [300, 700],
695+
source: 'pointer',
696+
pointerType: 'mouse',
697+
originalEvent: expect.any(PointerEvent),
698+
});
650699
});
651700

652701
it('ignores pointer events from non-captured pointers (multi-touch)', () => {

src/hooks/useResizer.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
6969
startPosition: number;
7070
startSizes: number[];
7171
pointerId: number;
72+
pointerType: 'mouse' | 'touch' | 'pen';
7273
element: HTMLElement | null;
7374
} | null>(null);
7475

@@ -111,7 +112,8 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
111112
(clientX: number, clientY: number) => {
112113
if (!dragStateRef.current || !mountedRef.current) return;
113114

114-
const { dividerIndex, startPosition, startSizes } = dragStateRef.current;
115+
const { dividerIndex, startPosition, startSizes, pointerType } =
116+
dragStateRef.current;
115117
const currentPosition = direction === 'horizontal' ? clientX : clientY;
116118

117119
let delta = currentPosition - startPosition;
@@ -142,6 +144,7 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
142144
onResize(newSizes, {
143145
sizes: newSizes,
144146
source: 'pointer',
147+
pointerType,
145148
});
146149
}
147150
},
@@ -186,7 +189,7 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
186189
}
187190

188191
// Release pointer capture
189-
const { element, pointerId } = dragStateRef.current;
192+
const { element, pointerId, pointerType } = dragStateRef.current;
190193
if (element?.hasPointerCapture?.(pointerId)) {
191194
element.releasePointerCapture(pointerId);
192195
}
@@ -207,6 +210,7 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
207210
latestOnResizeEnd(latestSizes, {
208211
sizes: latestSizes,
209212
source: 'pointer',
213+
pointerType,
210214
});
211215
}
212216

@@ -223,11 +227,14 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
223227
// Capture the pointer to receive all pointer events even if pointer leaves element
224228
element.setPointerCapture(e.pointerId);
225229

230+
const pointerType = e.pointerType as 'mouse' | 'touch' | 'pen';
231+
226232
dragStateRef.current = {
227233
dividerIndex,
228234
startPosition,
229235
startSizes: currentSizes,
230236
pointerId: e.pointerId,
237+
pointerType,
231238
element,
232239
};
233240

@@ -237,6 +244,7 @@ export function useResizer(options: UseResizerOptions): UseResizerResult {
237244
onResizeStart({
238245
sizes: currentSizes,
239246
source: 'pointer',
247+
pointerType,
240248
originalEvent: e.nativeEvent,
241249
});
242250
}

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ export type Size = string | number;
77
export interface ResizeEvent {
88
sizes: number[];
99
source: 'pointer' | 'keyboard';
10+
/** The type of pointer that initiated the resize (mouse, touch, or pen) */
11+
pointerType?: 'mouse' | 'touch' | 'pen';
1012
originalEvent?: PointerEvent | KeyboardEvent;
1113
}
1214

0 commit comments

Comments
 (0)