UNPKG

circuit-bricks

Version:

A modular, Lego-style SVG circuit component system for React (ALPHA - Not for production use)

254 lines (252 loc) 5.87 kB
import { isBrowser } from "./ssrUtils-DBIJQge-.mjs"; import { useEffect, useState } from "react"; //#region src/utils/responsiveUtils.ts /** * Breakpoint definitions */ const breakpoints = { xs: 0, sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1400 }; /** * Get current breakpoint based on width */ const getBreakpoint = (width) => { if (width >= breakpoints.xxl) return "xxl"; if (width >= breakpoints.xl) return "xl"; if (width >= breakpoints.lg) return "lg"; if (width >= breakpoints.md) return "md"; if (width >= breakpoints.sm) return "sm"; return "xs"; }; /** * Get device type based on width and user agent */ const getDeviceType = (width, userAgent = "") => { const isMobileUA = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent); const isTabletUA = /iPad|Android(?!.*Mobile)/i.test(userAgent); if (isMobileUA || width < breakpoints.md) return "mobile"; if (isTabletUA || width >= breakpoints.md && width < breakpoints.lg) return "tablet"; return "desktop"; }; /** * Hook for responsive screen information */ const useScreenInfo = () => { const [screenInfo, setScreenInfo] = useState({ width: 1024, height: 768, breakpoint: "lg", deviceType: "desktop", isPortrait: false, isLandscape: true, pixelRatio: 1 }); useEffect(() => { if (!isBrowser()) return; const updateScreenInfo = () => { const width = window.innerWidth; const height = window.innerHeight; const breakpoint = getBreakpoint(width); const deviceType = getDeviceType(width, navigator.userAgent); const isPortrait = height > width; const isLandscape = !isPortrait; const pixelRatio = window.devicePixelRatio || 1; setScreenInfo({ width, height, breakpoint, deviceType, isPortrait, isLandscape, pixelRatio }); }; updateScreenInfo(); window.addEventListener("resize", updateScreenInfo); window.addEventListener("orientationchange", updateScreenInfo); return () => { window.removeEventListener("resize", updateScreenInfo); window.removeEventListener("orientationchange", updateScreenInfo); }; }, []); return screenInfo; }; /** * Hook for breakpoint-specific values */ const useBreakpointValue = (values, fallback) => { const { breakpoint } = useScreenInfo(); const breakpointOrder = [ "xs", "sm", "md", "lg", "xl", "xxl" ]; const currentIndex = breakpointOrder.indexOf(breakpoint); if (values[breakpoint] !== void 0) return values[breakpoint]; for (let i = currentIndex - 1; i >= 0; i--) { const bp = breakpointOrder[i]; if (values[bp] !== void 0) return values[bp]; } for (let i = currentIndex + 1; i < breakpointOrder.length; i++) { const bp = breakpointOrder[i]; if (values[bp] !== void 0) return values[bp]; } return fallback; }; /** * Get responsive grid configuration based on device type */ const useResponsiveGridConfig = () => { const { deviceType } = useScreenInfo(); return useBreakpointValue({ xs: { gridSize: 15, snapThreshold: 12, minZoom: .25, maxZoom: 3, zoomStep: .15, panSensitivity: 1.2 }, sm: { gridSize: 18, snapThreshold: 15, minZoom: .3, maxZoom: 4, zoomStep: .2, panSensitivity: 1.1 }, md: { gridSize: 20, snapThreshold: 18, minZoom: .4, maxZoom: 5, zoomStep: .25, panSensitivity: 1 }, lg: { gridSize: 25, snapThreshold: 20, minZoom: .5, maxZoom: 8, zoomStep: .3, panSensitivity: .9 }, xl: { gridSize: 30, snapThreshold: 25, minZoom: .1, maxZoom: 10, zoomStep: .5, panSensitivity: .8 } }, { gridSize: 20, snapThreshold: 18, minZoom: .1, maxZoom: 10, zoomStep: .25, panSensitivity: 1 }); }; /** * Get responsive component configuration */ const useResponsiveComponentConfig = () => { return useBreakpointValue({ xs: { minComponentSize: 30, maxComponentSize: 80, portSize: 6, wireStrokeWidth: 2, fontSize: 10, iconSize: 16 }, sm: { minComponentSize: 35, maxComponentSize: 90, portSize: 7, wireStrokeWidth: 2.5, fontSize: 11, iconSize: 18 }, md: { minComponentSize: 40, maxComponentSize: 100, portSize: 8, wireStrokeWidth: 3, fontSize: 12, iconSize: 20 }, lg: { minComponentSize: 50, maxComponentSize: 120, portSize: 10, wireStrokeWidth: 3, fontSize: 14, iconSize: 24 }, xl: { minComponentSize: 60, maxComponentSize: 150, portSize: 12, wireStrokeWidth: 4, fontSize: 16, iconSize: 28 } }, { minComponentSize: 40, maxComponentSize: 100, portSize: 8, wireStrokeWidth: 3, fontSize: 12, iconSize: 20 }); }; /** * Check if current screen matches a breakpoint */ const useMatchesBreakpoint = (targetBreakpoint) => { const { breakpoint } = useScreenInfo(); const breakpointOrder = [ "xs", "sm", "md", "lg", "xl", "xxl" ]; const currentIndex = breakpointOrder.indexOf(breakpoint); const targetIndex = breakpointOrder.indexOf(targetBreakpoint); return currentIndex >= targetIndex; }; /** * Get optimal canvas dimensions for current screen */ const useOptimalCanvasDimensions = (containerWidth, containerHeight) => { const { width: screenWidth, height: screenHeight, deviceType } = useScreenInfo(); const width = containerWidth || screenWidth; const height = containerHeight || screenHeight; if (deviceType === "mobile") return { width: Math.min(width, screenWidth * .95), height: Math.min(height, screenHeight * .8) }; if (deviceType === "tablet") return { width: Math.min(width, screenWidth * .98), height: Math.min(height, screenHeight * .9) }; return { width, height }; }; //#endregion export { breakpoints, getBreakpoint, getDeviceType, useBreakpointValue, useMatchesBreakpoint, useOptimalCanvasDimensions, useResponsiveComponentConfig, useResponsiveGridConfig, useScreenInfo }; //# sourceMappingURL=responsiveUtils-CCZQdbIB.mjs.map