diff --git a/front/src/Utils/BreakpointsUtils.ts b/front/src/Utils/BreakpointsUtils.ts new file mode 100644 index 00000000..3cefb37d --- /dev/null +++ b/front/src/Utils/BreakpointsUtils.ts @@ -0,0 +1,112 @@ +type InternalBreakpoint = { + beforeBreakpoint: InternalBreakpoint | undefined; + nextBreakpoint: InternalBreakpoint | undefined; + pixels: number; +}; + +function generateBreakpointsMap(): Map { + // If is changed don't forget to also change it on SASS. + const breakpoints: { [key: string]: number } = { + xs: 0, + sm: 576, + md: 768, + lg: 992, + xl: 1200, + xxl: 1400, + }; + + let beforeBreakpoint: InternalBreakpoint | undefined; + let beforeBreakpointTag: string | undefined; + const mapRender = new Map(); + + for (const breakpoint in breakpoints) { + const newBreakpoint = { + beforeBreakpoint: beforeBreakpoint, + nextBreakpoint: undefined, + pixels: breakpoints[breakpoint], + }; + + if (beforeBreakpointTag && beforeBreakpoint) { + beforeBreakpoint.nextBreakpoint = newBreakpoint; + mapRender.set(beforeBreakpointTag, beforeBreakpoint); + } + + mapRender.set(breakpoint, { + beforeBreakpoint: beforeBreakpoint, + nextBreakpoint: undefined, + pixels: breakpoints[breakpoint], + }); + + beforeBreakpointTag = breakpoint; + beforeBreakpoint = newBreakpoint; + } + + return mapRender; +} + +const breakpoints = generateBreakpointsMap(); + +export type Breakpoint = "xs" | "sm" | "md" | "lg" | "xl" | "xxl"; + +export function isMediaBreakpointUp(breakpoint: Breakpoint): boolean { + if (breakpoint === "xxl") { + return true; + } + + const breakpointObject = breakpoints.get(breakpoint); + + if (!breakpointObject) { + throw new Error(`Unknown breakpoint: ${breakpoint}`); + } + + if (!breakpointObject.nextBreakpoint) { + return false; + } + + return breakpointObject.nextBreakpoint.pixels - 1 >= window.innerWidth; +} + +export function isMediaBreakpointDown(breakpoint: Breakpoint): boolean { + if (breakpoint === "xs") { + return true; + } + + const breakpointObject = breakpoints.get(breakpoint); + + if (!breakpointObject) { + throw new Error(`Unknown breakpoint: ${breakpoint}`); + } + + return breakpointObject.pixels <= window.innerWidth; +} + +export function isMediaBreakpointOnly(breakpoint: Breakpoint): boolean { + const breakpointObject = breakpoints.get(breakpoint); + + if (!breakpointObject) { + throw new Error(`Unknown breakpoint: ${breakpoint}`); + } + + return ( + breakpointObject.pixels <= window.innerWidth && + (!breakpointObject.nextBreakpoint || breakpointObject.nextBreakpoint.pixels - 1 >= window.innerWidth) + ); +} + +export function isMediaBreakpointBetween(startBreakpoint: Breakpoint, endBreakpoint: Breakpoint): boolean { + const startBreakpointObject = breakpoints.get(startBreakpoint); + const endBreakpointObject = breakpoints.get(endBreakpoint); + + if (!startBreakpointObject) { + throw new Error(`Unknown start breakpoint: ${startBreakpointObject}`); + } + + if (!endBreakpointObject) { + throw new Error(`Unknown end breakpoint: ${endBreakpointObject}`); + } + + return ( + startBreakpointObject.pixels <= innerWidth && + (!endBreakpointObject.nextBreakpoint || endBreakpointObject.nextBreakpoint.pixels - 1 >= window.innerWidth) + ); +} diff --git a/front/style/breakpoints.scss b/front/style/breakpoints.scss new file mode 100644 index 00000000..8b988d66 --- /dev/null +++ b/front/style/breakpoints.scss @@ -0,0 +1,102 @@ +@use "sass:map"; + +// If you modify this breakpoints don't forget to change it also in TS utils. +$grid-breakpoints: ( + xs: 0, + sm: 576px, + md: 768px, + lg: 992px, + xl: 1200px, + xxl: 1400px +); + +@function get-upper-breakpoint($breakpoint) { + @return map-get(( + xs: map.get($grid-breakpoints, "sm"), + sm: map.get($grid-breakpoints, "md"), + md: map.get($grid-breakpoints, "lg"), + lg: map.get($grid-breakpoints, "xl"), + xl: map.get($grid-breakpoints, "xxl"), + xxl: null, + ), $breakpoint); +} + +@function get-under-breakpoint($breakpoint) { + @return map-get(( + xs: null, + sm: map.get($grid-breakpoints, "xs"), + md: map.get($grid-breakpoints, "sm"), + lg: map.get($grid-breakpoints, "md"), + xl: map.get($grid-breakpoints, "lg"), + xxl: map.get($grid-breakpoints, "xl"), + ), $breakpoint); +} + +@mixin media-breakpoint-up($upTo) { + @if $upTo == 'xxl' { + @media only screen { + @content; + } + } @else { + $value: get-upper-breakpoint($upTo); + + @if $value != null { + $value: $value - 1px; + @media only screen and (max-width: $value) { + @content; + } + } + } +} + +@mixin media-breakpoint-down($downFrom) { + @if $downFrom == 'xs' { + @media only screen { + @content; + } + } @else { + $value: map.get($grid-breakpoints, $downFrom); + + @if $value != null { + @media only screen and (min-width: $value) { + @content; + } + } + } +} + +@mixin media-breakpoint-only($only) { + $maxValue: get-upper-breakpoint($only); + $minValue: map.get($grid-breakpoints, $only); + + @if $minValue == null { + + } @else if $maxValue != null { + $maxValue: $maxValue - 1px; + @media only screen and (min-width: $minValue) and (max-width: $maxValue) { + @content; + } + } @else { + @media only screen and (min-width: $minValue) { + @content; + } + } +} + +@mixin media-breakpoint-between($start, $end) { + $maxValue: get-upper-breakpoint($end); + $minValue: map.get($grid-breakpoints, $start); + + @if $minValue == null { + + } @else if $maxValue != null { + $maxValue: $maxValue - 1px; + @media only screen and (min-width: $minValue) and (max-width: $maxValue) { + @content; + } + } @else { + @media only screen and (min-width: $minValue) { + @content; + } + } +}