diff --git a/src/Breakpoints.ts b/src/Breakpoints.ts index c58bcf7..6eda310 100644 --- a/src/Breakpoints.ts +++ b/src/Breakpoints.ts @@ -1,5 +1,5 @@ import { MediaBreakpointProps } from "./Media" -import { propKey, createRuleSet, createClassName } from "./Utils" +import { createRuleSet, createClassName } from "./Utils" /** * A union of possible breakpoint props. @@ -42,12 +42,12 @@ export class Breakpoints { .map(breakpointAndValue => breakpointAndValue[0] as string) // List of all possible and valid `between` combinations - const betweenCombinations: Tuple[] = this._sortedBreakpoints + const betweenCombinations = this._sortedBreakpoints .slice(0, -1) .reduce( - (acc, b1, i) => [ + (acc: Tuple[], b1, i) => [ ...acc, - ...this._sortedBreakpoints.slice(i + 1).map(b2 => [b1, b2]), + ...this._sortedBreakpoints.slice(i + 1).map(b2 => [b1, b2] as Tuple), ], [] ) @@ -119,19 +119,22 @@ export class Breakpoints { } public toRuleSets() { - return Object.entries(this._mediaQueries).reduce((acc, [type, queries]) => { - queries.forEach((query, breakpoint) => { - // We need to invert the query, such that it matches when we want the - // element to be hidden. - acc.push( - createRuleSet( - createClassName(type, breakpoint), - `not all and ${query}` + return Object.entries(this._mediaQueries).reduce( + (acc: string[], [type, queries]) => { + queries.forEach((query, breakpoint) => { + // We need to invert the query, such that it matches when we want the + // element to be hidden. + acc.push( + createRuleSet( + createClassName(type, breakpoint), + `not all and ${query}` + ) ) - ) - }) - return acc - }, []) + }) + return acc + }, + [] + ) } public shouldRenderMediaQuery( @@ -139,45 +142,41 @@ export class Breakpoints { onlyRenderAt: string[] ): boolean { breakpointProps = this._normalizeProps(breakpointProps) - switch (propKey(breakpointProps)) { - case "lessThan": { - const width = this._breakpoints[breakpointProps.lessThan] - const lowestAllowedWidth = Math.min( - ...onlyRenderAt.map(breakpoint => this._breakpoints[breakpoint]) - ) - return lowestAllowedWidth < width - } - case "greaterThan": { - const width = this._breakpoints[ - this._findNextBreakpoint(breakpointProps.greaterThan) - ] - const highestAllowedWidth = Math.max( - ...onlyRenderAt.map(breakpoint => this._breakpoints[breakpoint]) - ) - return highestAllowedWidth >= width - } - case "greaterThanOrEqual": { - const width = this._breakpoints[breakpointProps.greaterThanOrEqual] - const highestAllowedWidth = Math.max( - ...onlyRenderAt.map(breakpoint => this._breakpoints[breakpoint]) - ) - return highestAllowedWidth >= width - } - case "between": { - // TODO: This is the only useful breakpoint to negate, but we’ll - // we’ll see when/if we need it. We could then also decide - // to add `oustide`. - const fromWidth = this._breakpoints[breakpointProps.between[0]] - const toWidth = this._breakpoints[breakpointProps.between[1]] - const allowedWidths = onlyRenderAt.map( - breakpoint => this._breakpoints[breakpoint] - ) - return !( - Math.max(...allowedWidths) < fromWidth || - Math.min(...allowedWidths) >= toWidth - ) - } + if (breakpointProps.lessThan) { + const width = this._breakpoints[breakpointProps.lessThan] + const lowestAllowedWidth = Math.min( + ...onlyRenderAt.map(breakpoint => this._breakpoints[breakpoint]) + ) + return lowestAllowedWidth < width + } else if (breakpointProps.greaterThan) { + const width = this._breakpoints[ + this._findNextBreakpoint(breakpointProps.greaterThan) + ] + const highestAllowedWidth = Math.max( + ...onlyRenderAt.map(breakpoint => this._breakpoints[breakpoint]) + ) + return highestAllowedWidth >= width + } else if (breakpointProps.greaterThanOrEqual) { + const width = this._breakpoints[breakpointProps.greaterThanOrEqual] + const highestAllowedWidth = Math.max( + ...onlyRenderAt.map(breakpoint => this._breakpoints[breakpoint]) + ) + return highestAllowedWidth >= width + } else if (breakpointProps.between) { + // TODO: This is the only useful breakpoint to negate, but we’ll + // we’ll see when/if we need it. We could then also decide + // to add `oustide`. + const fromWidth = this._breakpoints[breakpointProps.between[0]] + const toWidth = this._breakpoints[breakpointProps.between[1]] + const allowedWidths = onlyRenderAt.map( + breakpoint => this._breakpoints[breakpoint] + ) + return !( + Math.max(...allowedWidths) < fromWidth || + Math.min(...allowedWidths) >= toWidth + ) } + return false } public valuesWithBreakpointProps = ( @@ -229,34 +228,28 @@ export class Breakpoints { breakpointProps: MediaBreakpointProps ): string { breakpointProps = this._normalizeProps(breakpointProps) - switch (propKey(breakpointProps)) { - case "lessThan": { - const width = this._breakpoints[breakpointProps.lessThan] - return `(max-width:${width - 1}px)` - } - case "greaterThan": { - const width = this._breakpoints[ - this._findNextBreakpoint(breakpointProps.greaterThan) - ] - return `(min-width:${width}px)` - } - case "greaterThanOrEqual": { - const width = this._breakpoints[breakpointProps.greaterThanOrEqual] - return `(min-width:${width}px)` - } - case "between": { - // TODO: This is the only useful breakpoint to negate, but we’ll - // we’ll see when/if we need it. We could then also decide - // to add `outside`. - const fromWidth = this._breakpoints[breakpointProps.between[0]] - const toWidth = this._breakpoints[breakpointProps.between[1]] - return `(min-width:${fromWidth}px) and (max-width:${toWidth - 1}px)` - } - default: - throw new Error( - `Unexpected breakpoint props: ${JSON.stringify(breakpointProps)}` - ) + if (breakpointProps.lessThan) { + const width = this._breakpoints[breakpointProps.lessThan] + return `(max-width:${width - 1}px)` + } else if (breakpointProps.greaterThan) { + const width = this._breakpoints[ + this._findNextBreakpoint(breakpointProps.greaterThan) + ] + return `(min-width:${width}px)` + } else if (breakpointProps.greaterThanOrEqual) { + const width = this._breakpoints[breakpointProps.greaterThanOrEqual] + return `(min-width:${width}px)` + } else if (breakpointProps.between) { + // TODO: This is the only useful breakpoint to negate, but we’ll + // we’ll see when/if we need it. We could then also decide + // to add `outside`. + const fromWidth = this._breakpoints[breakpointProps.between[0]] + const toWidth = this._breakpoints[breakpointProps.between[1]] + return `(min-width:${fromWidth}px) and (max-width:${toWidth - 1}px)` } + throw new Error( + `Unexpected breakpoint props: ${JSON.stringify(breakpointProps)}` + ) } private _createBreakpointQueries( diff --git a/src/DynamicResponsive.tsx b/src/DynamicResponsive.tsx index c5325a0..74c0462 100644 --- a/src/DynamicResponsive.tsx +++ b/src/DynamicResponsive.tsx @@ -55,7 +55,7 @@ export function createResponsiveComponents() { > { constructor(props: ResponsiveProviderProps) { super(props) - let mediaQueryMatchers: MediaQueryMatchers + let mediaQueryMatchers: MediaQueryMatchers | undefined = undefined let mediaQueryMatches: MediaQueryMatches if (this.isSupportedEnvironment()) { @@ -63,11 +63,11 @@ export function createResponsiveComponents() { mediaQueryMatches = this.checkMatchers(mediaQueryMatchers) } else { mediaQueryMatches = Object.keys(props.mediaQueries).reduce( - (matches, key: M) => ({ + (matches, key) => ({ ...matches, [key]: !!props.initialMatchingMediaQueries && - props.initialMatchingMediaQueries.includes(key), + props.initialMatchingMediaQueries.includes(key as M), }), {} ) @@ -119,7 +119,7 @@ export function createResponsiveComponents() { */ mediaQueryStatusChangedCallback = () => { const mediaQueryMatches = this.checkMatchers( - this.state.mediaQueryMatchers + this.state.mediaQueryMatchers! ) this.setState({ mediaQueryMatches, diff --git a/src/Interactions.ts b/src/Interactions.ts index 009074c..a8ec9d4 100644 --- a/src/Interactions.ts +++ b/src/Interactions.ts @@ -16,12 +16,15 @@ export class Interactions { } public toRuleSets() { - return Object.entries(this._interactions).reduce((acc, [name, query]) => { - return [ - ...acc, - createRuleSet(createClassName("interaction", name), query), - ] - }, []) + return Object.entries(this._interactions).reduce( + (acc: string[], [name, query]) => { + return [ + ...acc, + createRuleSet(createClassName("interaction", name), query), + ] + }, + [] + ) } public get interactions() { diff --git a/src/Media.tsx b/src/Media.tsx index c2e5bc1..18d90e9 100644 --- a/src/Media.tsx +++ b/src/Media.tsx @@ -246,7 +246,10 @@ export interface CreateMediaResults { * Creates a list of your application’s breakpoints that support the given * widths and everything in between. */ - findBreakpointsForWidths(fromWidth: number, throughWidth: number): B[] + findBreakpointsForWidths( + fromWidth: number, + throughWidth: number + ): B[] | undefined /** * Finds the breakpoint that matches the given width. @@ -403,7 +406,7 @@ export function createMedia< } const type = propKey(breakpointProps) - const breakpoint = breakpointProps[type] + const breakpoint = breakpointProps[type]! className = createClassName(type, breakpoint) } diff --git a/src/Utils.ts b/src/Utils.ts index 161e9fe..da5a72e 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -35,7 +35,7 @@ export function createClassName( return [ "rrm", ...components.reduce( - (acc, breakpoint) => + (acc: string[], breakpoint) => Array.isArray(breakpoint) ? [...acc, ...breakpoint] : [...acc, breakpoint], diff --git a/tsconfig.json b/tsconfig.json index 40b43f0..9e0cb40 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,7 +15,8 @@ "outDir": "dist", "rootDir": "src", "skipLibCheck": true, - "target": "es2015" + "target": "es2015", + "strict": true }, "exclude": ["node_modules/*", "dist", "example", "src/**/__test__/*"] } diff --git a/tslint.json b/tslint.json index 17f2ce8..5075801 100644 --- a/tslint.json +++ b/tslint.json @@ -6,7 +6,7 @@ "jsx-boolean-value": [true, "never"], "jsx-no-lambda": false, "jsx-no-bind": false, - "max-classes-per-file": [false], + "max-classes-per-file": false, "member-access": [false], "member-ordering": false, "no-console": [true, "log", "error"], @@ -25,6 +25,7 @@ "types": { "visibilities": ["exported"] }, "variables": { "visibilities": ["exported"] } } - ] + ], + "no-unnecessary-initializer": false } }