Skip to content

Commit 665bff5

Browse files
committed
fix(api): fire zoom callbacks from programmatic zoomIn/resetTransform
handleZoomToViewCenter and resetTransformations now emit onZoomStart, onZoom, and onZoomStop callbacks, matching the sequence fired by user-driven wheel/pinch gestures. Also assigns ref context on init for stable ref API access. Closes #369 Ref #553 Made-with: Cursor
1 parent 025a10a commit 665bff5

3 files changed

Lines changed: 48 additions & 1 deletion

File tree

src/core/handlers/handlers.utils.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { handleZoomToPoint } from "../zoom/zoom.logic";
44
import { animate } from "../animations/animations.utils";
55
import { createState } from "../../utils/state.utils";
66
import { checkZoomBounds } from "../zoom/zoom.utils";
7-
import { roundNumber } from "../../utils";
7+
import { getContext, handleCallback, roundNumber } from "../../utils";
88
import {
99
calculateBounds,
1010
getMouseBoundedPosition,
@@ -70,7 +70,21 @@ export function handleZoomToViewCenter(
7070
);
7171
}
7272

73+
const { onZoomStart, onZoom, onZoomStop } = contextInstance.props;
74+
const event = new MouseEvent("mousemove", { bubbles: true });
75+
const ctx = getContext(contextInstance);
76+
handleCallback(ctx, event, onZoomStart);
77+
handleCallback(ctx, event, onZoom);
7378
animate(contextInstance, targetState, animationTime, animationType);
79+
const win =
80+
wrapperComponent.ownerDocument?.defaultView ??
81+
(typeof window !== "undefined" ? window : null);
82+
if (win) {
83+
win.setTimeout(() => {
84+
if (!contextInstance.mounted) return;
85+
handleCallback(getContext(contextInstance), event, onZoomStop);
86+
}, animationTime);
87+
}
7488
}
7589

7690
export function resetTransformations(
@@ -116,7 +130,22 @@ export function resetTransformations(
116130
}
117131

118132
onResetTransformation?.();
133+
134+
const { onZoomStart, onZoom, onZoomStop } = contextInstance.props;
135+
const event = new MouseEvent("mousemove", { bubbles: true });
136+
const ctx = getContext(contextInstance);
137+
handleCallback(ctx, event, onZoomStart);
138+
handleCallback(ctx, event, onZoom);
119139
animate(contextInstance, newState, animationTime, animationType);
140+
const win =
141+
wrapperComponent.ownerDocument?.defaultView ??
142+
(typeof window !== "undefined" ? window : null);
143+
if (win) {
144+
win.setTimeout(() => {
145+
if (!contextInstance.mounted) return;
146+
handleCallback(getContext(contextInstance), event, onZoomStop);
147+
}, animationTime);
148+
}
120149
}
121150

122151
export function getOffset(

src/core/instance.core.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
getTransformStyles,
1818
makePassiveEventOption,
1919
getCenterPosition,
20+
assignRef,
2021
} from "../utils";
2122
import { handleCancelAnimation } from "./animations/animations.utils";
2223
import { isWheelAllowed, isWheelPanningAllowed } from "./wheel/wheel.utils";
@@ -633,5 +634,6 @@ export class ZoomPanPinch {
633634
this.isInitialized = true;
634635
const ctx = getContext(this);
635636
handleCallback(ctx, undefined, this.props.onInit);
637+
assignRef(this.props.ref, ctx);
636638
};
637639
}

src/utils/ref.utils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,22 @@
11
/* eslint-disable no-param-reassign */
22
import type * as React from "react";
33

4+
export function assignRef<T>(
5+
ref:
6+
| ((value: T | null) => void)
7+
| React.MutableRefObject<T | null>
8+
| null
9+
| undefined,
10+
value: T | null,
11+
): void {
12+
if (ref == null) return;
13+
if (typeof ref === "function") {
14+
ref(value);
15+
} else {
16+
ref.current = value;
17+
}
18+
}
19+
420
export function mergeRefs<T = any>(
521
refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>>,
622
): React.RefCallback<T> {

0 commit comments

Comments
 (0)