From 3a566a292c52b9da4de1c7c37a26ea0f62890eea Mon Sep 17 00:00:00 2001 From: Ryan Di Date: Fri, 9 May 2025 18:46:54 +1000 Subject: [PATCH] rename and restrict constraint mode --- packages/excalidraw/components/App.tsx | 8 ++--- .../excalidraw/scene/scrollConstraints.ts | 33 +++++++++++++++++-- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 4441f607a..06e5427eb 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -2974,9 +2974,7 @@ class App extends React.Component { } if (this.state.scrollConstraints?.animateOnNextUpdate) { - const newState = constrainScrollState(this.state, { - allowOverscroll: false, - }); + const newState = constrainScrollState(this.state, "rigid"); const fromValues = { scrollX: this.state.scrollX, scrollY: this.state.scrollY, @@ -5041,7 +5039,7 @@ class App extends React.Component { state, ), }, - { disableAnimation: true }, + "loose", ), ); } @@ -11353,7 +11351,7 @@ class App extends React.Component { ...this.state, scrollConstraints, }, - { allowOverscroll: false }, + "rigid", ); this.animateToConstrainedArea( diff --git a/packages/excalidraw/scene/scrollConstraints.ts b/packages/excalidraw/scene/scrollConstraints.ts index 4920fbaa5..e1bbc35f3 100644 --- a/packages/excalidraw/scene/scrollConstraints.ts +++ b/packages/excalidraw/scene/scrollConstraints.ts @@ -417,18 +417,27 @@ export const decodeConstraints = (encoded: string): ScrollConstraints => { } }; -type Options = { allowOverscroll?: boolean; disableAnimation?: boolean }; +type Options = { allowOverscroll: boolean; disableAnimation: boolean }; +const DEFAULT_OPTION: Options = { + allowOverscroll: true, + disableAnimation: false, +}; /** * Constrains the AppState scroll values within the defined scroll constraints. * + * constraintMode can be "elastic", "rigid", or "loose": + * - "elastic": snaps to constraints but allows overscroll + * - "rigid": snaps to constraints without overscroll + * - "loose": allows overscroll and disables animation/snapping to constraints + * * @param state - The original AppState. * @param options - Options for allowing overscroll and disabling animation. * @returns A new AppState object with constrained scroll values. */ export const constrainScrollState = ( state: AppState, - options?: Options, + constraintMode: "elastic" | "rigid" | "loose" = "elastic", ): AppState => { if (!state.scrollConstraints) { return state; @@ -442,7 +451,25 @@ export const constrainScrollState = ( zoom, } = state; - const { allowOverscroll = true, disableAnimation = false } = options || {}; + let allowOverscroll: boolean; + let disableAnimation: boolean; + + switch (constraintMode) { + case "elastic": + ({ allowOverscroll, disableAnimation } = DEFAULT_OPTION); + break; + case "rigid": + allowOverscroll = false; + disableAnimation = false; + break; + case "loose": + allowOverscroll = true; + disableAnimation = true; + break; + default: + ({ allowOverscroll, disableAnimation } = DEFAULT_OPTION); + break; + } const scrollConstraints = alignScrollConstraints(inverseScrollConstraints);