Skip to content

Commit 3643a47

Browse files
authored
fix: Fixed auto align to bounds bugs (#486)
* fix: Fixed auto align to bounds bugs * fix: Fixed typescript issues and format code styles * fix: Fixed build tools warnings * fix: Fixed observer * feat: Add resizeAlignmentTime prop * feat: Revert resizeAlignmentTime and add handleAlignToBounds params
1 parent 800beb1 commit 3643a47

7 files changed

Lines changed: 61 additions & 32 deletions

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"scripts": {
1515
"build": "rollup -c",
1616
"build:docs": "build-storybook",
17-
"start": "DISABLE_ESLINT_PLUGIN=true start-storybook -p 6006 --no-manager-cache",
17+
"start": "cross-env DISABLE_ESLINT_PLUGIN=true start-storybook -p 6006 --no-manager-cache",
1818
"test": "jest",
1919
"lint": "eslint . --ext .js,.jsx,.tsx,.ts --fix",
2020
"format": "prettier --write .",
@@ -93,6 +93,7 @@
9393
"ts-jest": "^29.0.3",
9494
"ts-loader": "^9.4.2",
9595
"ts-node": "~10.9.1",
96+
"tslib": "^2.6.3",
9697
"typescript": "^4.2.3",
9798
"webpack": "5",
9899
"webpack-cli": "^5.0.1"

rollup.config.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,20 @@ export default [
2626
plugins: [
2727
external(),
2828
babel({
29+
babelHelpers: "bundled",
2930
exclude: "node_modules/**",
3031
}),
3132
del({ targets: ["dist/*"] }),
32-
typescript({ sourceMap: false, declaration: false }),
33+
typescript({ declaration: false }),
3334
postcss({
3435
modules: true,
3536
}),
3637
],
38+
onwarn(error, warn) {
39+
if (error.code !== "CIRCULAR_DEPENDENCY") {
40+
warn(error);
41+
}
42+
},
3743
external: Object.keys(pkg.peerDependencies || {}),
3844
},
3945
{

src/components/mini-map/mini-map.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@ export const MiniMap: React.FC<MiniMapProps> = ({
5757

5858
return {
5959
width: rect.width,
60-
height: rect.height
60+
height: rect.height,
6161
};
6262
}
6363
return {
6464
width: 0,
65-
height: 0
65+
height: 0,
6666
};
6767
}, [instance.wrapperComponent]);
6868

src/constants/state.constants.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { LibrarySetup, ReactZoomPanPinchState, ReactZoomPanPinchBaseClasses } from "../models/context.model";
1+
import {
2+
LibrarySetup,
3+
ReactZoomPanPinchState,
4+
ReactZoomPanPinchBaseClasses,
5+
} from "../models/context.model";
26

37
export const initialState: ReactZoomPanPinchState = {
48
previousScale: 1,
@@ -80,4 +84,4 @@ export const initialSetup: LibrarySetup = {
8084
export const baseClasses: ReactZoomPanPinchBaseClasses = {
8185
wrapperClass: "react-transform-wrapper",
8286
contentClass: "react-transform-component",
83-
};
87+
};

src/core/instance.core.ts

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
handlePanning,
3737
handlePanningEnd,
3838
handlePanningStart,
39+
handleAlignToBounds,
3940
} from "./pan/panning.logic";
4041
import {
4142
handlePinchStart,
@@ -46,7 +47,6 @@ import {
4647
handleDoubleClick,
4748
isDoubleClickAllowed,
4849
} from "./double-click/double-click.logic";
49-
import { handleAlignToScaleBounds } from "./zoom/zoom.logic";
5050

5151
type StartCoordsType = { x: number; y: number } | null;
5252

@@ -60,7 +60,7 @@ export class ZoomPanPinch {
6060

6161
public transformState: ReactZoomPanPinchState;
6262
public setup: LibrarySetup;
63-
public observer: ResizeObserver;
63+
public observer?: ResizeObserver;
6464
public onChangeCallbacks: Set<(ctx: ReactZoomPanPinchRef) => void> =
6565
new Set();
6666
public onInitCallbacks: Set<(ctx: ReactZoomPanPinchRef) => void> = new Set();
@@ -158,7 +158,7 @@ export class ZoomPanPinch {
158158
document.removeEventListener("mouseleave", this.clearPanning, passive);
159159

160160
handleCancelAnimation(this);
161-
this.observer.disconnect();
161+
this.observer?.disconnect();
162162
};
163163

164164
handleInitializeWrapperEvents = (wrapper: HTMLDivElement): void => {
@@ -172,40 +172,50 @@ export class ZoomPanPinch {
172172
wrapper.addEventListener("touchend", this.onTouchPanningStop, passive);
173173
};
174174

175-
handleInitialize = (contentComponent: HTMLDivElement): void => {
175+
handleInitialize = (
176+
wrapper: HTMLDivElement,
177+
contentComponent: HTMLDivElement,
178+
): void => {
176179
let isCentered = false;
177-
180+
178181
const { centerOnInit } = this.setup;
179182

183+
const hasTarget = (entries: ResizeObserverEntry[], target: Element) => {
184+
for (const entry of entries) {
185+
if (entry.target === target) {
186+
return true;
187+
}
188+
}
189+
190+
return false;
191+
};
192+
180193
this.applyTransformation();
181194
this.onInitCallbacks.forEach((callback) => {
182195
callback(getContext(this));
183196
});
184197

185198
this.observer = new ResizeObserver((entries) => {
186-
for(const entry of entries) {
187-
if(entry.target === contentComponent) {
188-
if(centerOnInit && !isCentered) {
189-
const currentWidth = contentComponent.offsetWidth;
190-
const currentHeight = contentComponent.offsetHeight;
191-
192-
if (currentWidth > 0 || currentHeight > 0) {
193-
isCentered = true;
194-
195-
this.setCenter();
196-
}
197-
} else {
198-
const { pinchMidpoint } = this;
199-
200-
handleAlignToScaleBounds(this, pinchMidpoint?.x, pinchMidpoint?.y);
201-
}
199+
if (hasTarget(entries, wrapper) || hasTarget(entries, contentComponent)) {
200+
if (centerOnInit && !isCentered) {
201+
const currentWidth = contentComponent.offsetWidth;
202+
const currentHeight = contentComponent.offsetHeight;
202203

203-
break;
204+
if (currentWidth > 0 || currentHeight > 0) {
205+
isCentered = true;
206+
207+
this.setCenter();
208+
}
209+
} else {
210+
handleCancelAnimation(this);
211+
handleCalculateBounds(this, this.transformState.scale);
212+
handleAlignToBounds(this, 0);
204213
}
205214
}
206215
});
207216

208217
// Start observing the target node for configured mutations
218+
this.observer.observe(wrapper);
209219
this.observer.observe(contentComponent);
210220
};
211221

@@ -565,7 +575,7 @@ export class ZoomPanPinch {
565575
this.contentComponent = contentComponent;
566576
handleCalculateBounds(this, this.transformState.scale);
567577
this.handleInitializeWrapperEvents(wrapperComponent);
568-
this.handleInitialize(contentComponent);
578+
this.handleInitialize(wrapperComponent, contentComponent);
569579
this.initializeWindowEvents();
570580
this.isInitialized = true;
571581
const ctx = getContext(this);

src/core/pan/panning.logic.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export function handlePanningStart(
3232

3333
export function handleAlignToBounds(
3434
contextInstance: ReactZoomPanPinchContext,
35+
customAnimationTime?: number,
3536
): void {
3637
const { scale } = contextInstance.transformState;
3738
const { minScale, alignmentAnimation } = contextInstance.setup;
@@ -45,7 +46,12 @@ export function handleAlignToBounds(
4546
const targetState = handlePanToBounds(contextInstance);
4647

4748
if (targetState) {
48-
animate(contextInstance, targetState, animationTime, animationType);
49+
animate(
50+
contextInstance,
51+
targetState,
52+
customAnimationTime ?? animationTime,
53+
animationType,
54+
);
4955
}
5056
}
5157

src/utils/helpers.utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ export const isExcludedNode = (
66
node: HTMLElement,
77
excluded: string[],
88
): boolean => {
9-
return excluded.some((exclude) =>
10-
node.matches(`${matchPrefix} ${exclude}, ${matchPrefix} .${exclude}, ${matchPrefix} ${exclude} *, ${matchPrefix} .${exclude} *`),
9+
return excluded.some((exclude) =>
10+
node.matches(
11+
`${matchPrefix} ${exclude}, ${matchPrefix} .${exclude}, ${matchPrefix} ${exclude} *, ${matchPrefix} .${exclude} *`,
12+
),
1113
);
1214
};
1315

0 commit comments

Comments
 (0)