Skip to content

Commit

Permalink
fix: Fixed auto align to bounds bugs (#486)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nuintun authored Jul 3, 2024
1 parent 800beb1 commit 3643a47
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 32 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"scripts": {
"build": "rollup -c",
"build:docs": "build-storybook",
"start": "DISABLE_ESLINT_PLUGIN=true start-storybook -p 6006 --no-manager-cache",
"start": "cross-env DISABLE_ESLINT_PLUGIN=true start-storybook -p 6006 --no-manager-cache",
"test": "jest",
"lint": "eslint . --ext .js,.jsx,.tsx,.ts --fix",
"format": "prettier --write .",
Expand Down Expand Up @@ -93,6 +93,7 @@
"ts-jest": "^29.0.3",
"ts-loader": "^9.4.2",
"ts-node": "~10.9.1",
"tslib": "^2.6.3",
"typescript": "^4.2.3",
"webpack": "5",
"webpack-cli": "^5.0.1"
Expand Down
8 changes: 7 additions & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,20 @@ export default [
plugins: [
external(),
babel({
babelHelpers: "bundled",
exclude: "node_modules/**",
}),
del({ targets: ["dist/*"] }),
typescript({ sourceMap: false, declaration: false }),
typescript({ declaration: false }),
postcss({
modules: true,
}),
],
onwarn(error, warn) {
if (error.code !== "CIRCULAR_DEPENDENCY") {
warn(error);
}
},
external: Object.keys(pkg.peerDependencies || {}),
},
{
Expand Down
4 changes: 2 additions & 2 deletions src/components/mini-map/mini-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ export const MiniMap: React.FC<MiniMapProps> = ({

return {
width: rect.width,
height: rect.height
height: rect.height,
};
}
return {
width: 0,
height: 0
height: 0,
};
}, [instance.wrapperComponent]);

Expand Down
8 changes: 6 additions & 2 deletions src/constants/state.constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { LibrarySetup, ReactZoomPanPinchState, ReactZoomPanPinchBaseClasses } from "../models/context.model";
import {
LibrarySetup,
ReactZoomPanPinchState,
ReactZoomPanPinchBaseClasses,
} from "../models/context.model";

export const initialState: ReactZoomPanPinchState = {
previousScale: 1,
Expand Down Expand Up @@ -80,4 +84,4 @@ export const initialSetup: LibrarySetup = {
export const baseClasses: ReactZoomPanPinchBaseClasses = {
wrapperClass: "react-transform-wrapper",
contentClass: "react-transform-component",
};
};
56 changes: 33 additions & 23 deletions src/core/instance.core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
handlePanning,
handlePanningEnd,
handlePanningStart,
handleAlignToBounds,
} from "./pan/panning.logic";
import {
handlePinchStart,
Expand All @@ -46,7 +47,6 @@ import {
handleDoubleClick,
isDoubleClickAllowed,
} from "./double-click/double-click.logic";
import { handleAlignToScaleBounds } from "./zoom/zoom.logic";

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

Expand All @@ -60,7 +60,7 @@ export class ZoomPanPinch {

public transformState: ReactZoomPanPinchState;
public setup: LibrarySetup;
public observer: ResizeObserver;
public observer?: ResizeObserver;
public onChangeCallbacks: Set<(ctx: ReactZoomPanPinchRef) => void> =
new Set();
public onInitCallbacks: Set<(ctx: ReactZoomPanPinchRef) => void> = new Set();
Expand Down Expand Up @@ -158,7 +158,7 @@ export class ZoomPanPinch {
document.removeEventListener("mouseleave", this.clearPanning, passive);

handleCancelAnimation(this);
this.observer.disconnect();
this.observer?.disconnect();
};

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

handleInitialize = (contentComponent: HTMLDivElement): void => {
handleInitialize = (
wrapper: HTMLDivElement,
contentComponent: HTMLDivElement,
): void => {
let isCentered = false;

const { centerOnInit } = this.setup;

const hasTarget = (entries: ResizeObserverEntry[], target: Element) => {
for (const entry of entries) {

Check failure on line 184 in src/core/instance.core.ts

View workflow job for this annotation

GitHub Actions / Run tests

iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations
if (entry.target === target) {
return true;
}
}

return false;
};

this.applyTransformation();
this.onInitCallbacks.forEach((callback) => {
callback(getContext(this));
});

this.observer = new ResizeObserver((entries) => {
for(const entry of entries) {
if(entry.target === contentComponent) {
if(centerOnInit && !isCentered) {
const currentWidth = contentComponent.offsetWidth;
const currentHeight = contentComponent.offsetHeight;

if (currentWidth > 0 || currentHeight > 0) {
isCentered = true;

this.setCenter();
}
} else {
const { pinchMidpoint } = this;

handleAlignToScaleBounds(this, pinchMidpoint?.x, pinchMidpoint?.y);
}
if (hasTarget(entries, wrapper) || hasTarget(entries, contentComponent)) {
if (centerOnInit && !isCentered) {
const currentWidth = contentComponent.offsetWidth;
const currentHeight = contentComponent.offsetHeight;

break;
if (currentWidth > 0 || currentHeight > 0) {
isCentered = true;

this.setCenter();
}
} else {
handleCancelAnimation(this);
handleCalculateBounds(this, this.transformState.scale);
handleAlignToBounds(this, 0);
}
}
});

// Start observing the target node for configured mutations
this.observer.observe(wrapper);
this.observer.observe(contentComponent);
};

Expand Down Expand Up @@ -565,7 +575,7 @@ export class ZoomPanPinch {
this.contentComponent = contentComponent;
handleCalculateBounds(this, this.transformState.scale);
this.handleInitializeWrapperEvents(wrapperComponent);
this.handleInitialize(contentComponent);
this.handleInitialize(wrapperComponent, contentComponent);
this.initializeWindowEvents();
this.isInitialized = true;
const ctx = getContext(this);
Expand Down
8 changes: 7 additions & 1 deletion src/core/pan/panning.logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export function handlePanningStart(

export function handleAlignToBounds(
contextInstance: ReactZoomPanPinchContext,
customAnimationTime?: number,
): void {
const { scale } = contextInstance.transformState;
const { minScale, alignmentAnimation } = contextInstance.setup;
Expand All @@ -45,7 +46,12 @@ export function handleAlignToBounds(
const targetState = handlePanToBounds(contextInstance);

if (targetState) {
animate(contextInstance, targetState, animationTime, animationType);
animate(
contextInstance,
targetState,
customAnimationTime ?? animationTime,
animationType,
);
}
}

Expand Down
6 changes: 4 additions & 2 deletions src/utils/helpers.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ export const isExcludedNode = (
node: HTMLElement,
excluded: string[],
): boolean => {
return excluded.some((exclude) =>
node.matches(`${matchPrefix} ${exclude}, ${matchPrefix} .${exclude}, ${matchPrefix} ${exclude} *, ${matchPrefix} .${exclude} *`),
return excluded.some((exclude) =>
node.matches(
`${matchPrefix} ${exclude}, ${matchPrefix} .${exclude}, ${matchPrefix} ${exclude} *, ${matchPrefix} .${exclude} *`,
),
);
};

Expand Down

0 comments on commit 3643a47

Please sign in to comment.