From 7f62539435fc00bd0a7daab5d43ffe77a69d9e10 Mon Sep 17 00:00:00 2001 From: Oleg Isonen Date: Thu, 15 Dec 2022 17:33:59 +0000 Subject: [PATCH] start the smallest breakpoint at 0 and use the upper bound to set the canvas size --- .../breakpoints/use-next-breakpoint.ts | 30 ++++++++++++++ .../breakpoints/use-subscribe-breakpoints.ts | 1 + .../breakpoints/use-update-canvas-width.ts | 35 +++++++---------- .../features/breakpoints/width-setting.tsx | 39 +++---------------- packages/react-sdk/src/css/breakpoints.ts | 2 +- 5 files changed, 52 insertions(+), 55 deletions(-) create mode 100644 apps/designer/app/designer/features/breakpoints/use-next-breakpoint.ts diff --git a/apps/designer/app/designer/features/breakpoints/use-next-breakpoint.ts b/apps/designer/app/designer/features/breakpoints/use-next-breakpoint.ts new file mode 100644 index 0000000000..2229fddb12 --- /dev/null +++ b/apps/designer/app/designer/features/breakpoints/use-next-breakpoint.ts @@ -0,0 +1,30 @@ +import { useMemo } from "react"; +import { useSelectedBreakpoint } from "~/designer/shared/nano-states"; +import { useBreakpoints } from "~/shared/nano-states"; +import { utils } from "@webstudio-is/project"; + +/** + * Return the next breakpoint from the currently selected one, sorted by the `sort()` + */ +export const useNextBreakpoint = () => { + const [selectedBreakpoint] = useSelectedBreakpoint(); + const [breakpoints] = useBreakpoints(); + + const sortedBreakpoints = useMemo( + () => utils.breakpoints.sort(breakpoints), + [breakpoints] + ); + + return useMemo(() => { + if (selectedBreakpoint === undefined) { + return; + } + const index = sortedBreakpoints.findIndex( + (breakpoint) => breakpoint.id === selectedBreakpoint.id + ); + if (index === -1) { + return undefined; + } + return sortedBreakpoints[index + 1]; + }, [sortedBreakpoints, selectedBreakpoint]); +}; diff --git a/apps/designer/app/designer/features/breakpoints/use-subscribe-breakpoints.ts b/apps/designer/app/designer/features/breakpoints/use-subscribe-breakpoints.ts index 4e1439bdf5..3dc12d7a1f 100644 --- a/apps/designer/app/designer/features/breakpoints/use-subscribe-breakpoints.ts +++ b/apps/designer/app/designer/features/breakpoints/use-subscribe-breakpoints.ts @@ -3,6 +3,7 @@ import { useSubscribe } from "~/shared/pubsub"; import { useSelectedBreakpoint } from "~/designer/shared/nano-states"; import { useBreakpoints } from "~/shared/nano-states"; import { utils } from "@webstudio-is/project"; + export const useSubscribeBreakpoints = () => { const [breakpoints, setBreakpoints] = useBreakpoints(); const [selectedBreakpoint, setSelectedBreakpoint] = useSelectedBreakpoint(); diff --git a/apps/designer/app/designer/features/breakpoints/use-update-canvas-width.ts b/apps/designer/app/designer/features/breakpoints/use-update-canvas-width.ts index 854923e752..704cfd8bc1 100644 --- a/apps/designer/app/designer/features/breakpoints/use-update-canvas-width.ts +++ b/apps/designer/app/designer/features/breakpoints/use-update-canvas-width.ts @@ -4,34 +4,26 @@ import { useCanvasWidth, } from "~/designer/shared/nano-states"; import { useIsPreviewMode } from "~/shared/nano-states"; +import { useNextBreakpoint } from "./use-next-breakpoint"; import { minWidth } from "./width-setting"; export const useUpdateCanvasWidth = () => { const [selectedBreakpoint] = useSelectedBreakpoint(); const [canvasWidth, setCanvasWidth] = useCanvasWidth(); const [isPreviewMode] = useIsPreviewMode(); + const nextBreakpoint = useNextBreakpoint(); // Ensure the size is within currently selected breakpoint when returning to design mode out of preview mode, // because preview mode enables resizing without constraining to the selected breakpoint. useEffect(() => { - if (isPreviewMode === true || selectedBreakpoint === undefined) { + if (isPreviewMode || selectedBreakpoint === undefined) { return; } - setCanvasWidth(Math.max(selectedBreakpoint.minWidth, minWidth)); - }, [isPreviewMode, selectedBreakpoint, setCanvasWidth]); - - useEffect(() => { - if (selectedBreakpoint === undefined) { - return; - } - - if (selectedBreakpoint.minWidth === 0) { - setCanvasWidth(minWidth); - return; - } - - setCanvasWidth(Math.max(selectedBreakpoint.minWidth, minWidth)); - }, [selectedBreakpoint, setCanvasWidth]); + const nextWidth = nextBreakpoint + ? nextBreakpoint.minWidth - 1 + : selectedBreakpoint.minWidth; + setCanvasWidth(Math.max(nextWidth, minWidth)); + }, [isPreviewMode, nextBreakpoint, selectedBreakpoint, setCanvasWidth]); // This fallback is needed for cases when something unexpected loads in the iframe. // In that case the width remains 0, and user is unable to see what has loaded, @@ -39,12 +31,13 @@ export const useUpdateCanvasWidth = () => { // The delay is used to make sure we don't set the fallback width too early, // because when canvas loads normally this will cause a jump in the width. useEffect(() => { - if (canvasWidth === 0) { - const timeout = setTimeout(() => { - setCanvasWidth(600); - }, 3000); - return () => clearTimeout(timeout); + if (canvasWidth !== 0) { + return; } + const timeoutId = setTimeout(() => { + setCanvasWidth(600); + }, 3000); + return () => clearTimeout(timeoutId); }, [canvasWidth, setCanvasWidth]); // Set the initial canvas width based on the selected breakpoint upper bound, which starts where the next breakpoint begins. diff --git a/apps/designer/app/designer/features/breakpoints/width-setting.tsx b/apps/designer/app/designer/features/breakpoints/width-setting.tsx index 92f815cd5b..20e3722a4b 100644 --- a/apps/designer/app/designer/features/breakpoints/width-setting.tsx +++ b/apps/designer/app/designer/features/breakpoints/width-setting.tsx @@ -1,44 +1,17 @@ -import { useMemo } from "react"; import { useCanvasWidth, useSelectedBreakpoint, } from "~/designer/shared/nano-states"; import { Text, Flex, Slider } from "@webstudio-is/design-system"; -import { useBreakpoints, useIsPreviewMode } from "~/shared/nano-states"; -import { utils } from "@webstudio-is/project"; +import { useIsPreviewMode } from "~/shared/nano-states"; +import { useNextBreakpoint } from "./use-next-breakpoint"; // Doesn't make sense to allow resizing the canvas lower/higher than this. export const minWidth = 50; export const maxWidth = 3000; -/** - * Return the next breakpoint from the currently selected one, sorted by the `sort()` - */ -const useNextBreakpoint = () => { - const [selectedBreakpoint] = useSelectedBreakpoint(); - const [breakpoints] = useBreakpoints(); - - const sortedBreakpoints = useMemo( - () => utils.breakpoints.sort(breakpoints), - [breakpoints] - ); - - return useMemo(() => { - if (selectedBreakpoint === undefined) { - return; - } - const index = sortedBreakpoints.findIndex( - (breakpoint) => breakpoint.id === selectedBreakpoint.id - ); - if (index === -1) { - return undefined; - } - return sortedBreakpoints[index + 1]; - }, [sortedBreakpoints, selectedBreakpoint]); -}; - export const WidthSetting = () => { - const [value, setValue] = useCanvasWidth(); + const [canvasWidth, setCanvasWidth] = useCanvasWidth(); const [selectedBreakpoint] = useSelectedBreakpoint(); const nextBreakpoint = useNextBreakpoint(); const [isPreviewMode] = useIsPreviewMode(); @@ -69,12 +42,12 @@ export const WidthSetting = () => { { - setValue(value); + setCanvasWidth(value); }} /> - {`${value}px`} + {`${canvasWidth}px`} ); diff --git a/packages/react-sdk/src/css/breakpoints.ts b/packages/react-sdk/src/css/breakpoints.ts index 3b7357eb3b..0fa2522a1a 100644 --- a/packages/react-sdk/src/css/breakpoints.ts +++ b/packages/react-sdk/src/css/breakpoints.ts @@ -3,7 +3,7 @@ import type { Breakpoint } from "@webstudio-is/css-data"; export type BaseBreakpoint = Pick; export const initialBreakpoints: Array = [ - { label: "Mobile", minWidth: 360 }, + { label: "Mobile", minWidth: 0 }, { label: "Tablet", minWidth: 768 }, { label: "Laptop", minWidth: 1024 }, { label: "Desktop", minWidth: 1280 },