From 389f091101eaa9df8cdd87b1084d0d83d8181299 Mon Sep 17 00:00:00 2001 From: Justin Bennett Date: Sat, 12 Sep 2020 11:36:23 -0400 Subject: [PATCH] Expand generic names to be more descriptive --- src/Breakpoints.ts | 75 ++++++++++++++++++++----------------- src/Media.tsx | 65 ++++++++++++++++++-------------- src/MediaQueries.ts | 4 +- src/Utils.ts | 4 +- src/__test__/Media.test.tsx | 6 +-- src/index.tsx | 2 +- 6 files changed, 84 insertions(+), 72 deletions(-) diff --git a/src/Breakpoints.ts b/src/Breakpoints.ts index ea04d3a..143fea3 100644 --- a/src/Breakpoints.ts +++ b/src/Breakpoints.ts @@ -4,9 +4,12 @@ import { createRuleSet, createClassName } from "./Utils" /** * A union of possible breakpoint props. */ -export type MediaBreakpointKey = keyof MediaBreakpointProps +export type BreakpointConstraintKey = keyof MediaBreakpointProps -type ValueBreakpointPropsTuple = [T, MediaBreakpointProps] +type ValueBreakpointPropsTuple = [ + SizeValue, + MediaBreakpointProps +] type Tuple = [string, string] @@ -14,7 +17,7 @@ function breakpointKey(breakpoint: string | Tuple) { return Array.isArray(breakpoint) ? breakpoint.join("-") : breakpoint } -export enum BreakpointKey { +export enum BreakpointConstraint { at = "at", lessThan = "lessThan", greaterThan = "greaterThan", @@ -26,20 +29,20 @@ export enum BreakpointKey { * Encapsulates all breakpoint data needed by the Media component. The data is * generated on initialization so no further runtime work is necessary. */ -export class Breakpoints { +export class Breakpoints { static validKeys() { return [ - BreakpointKey.at, - BreakpointKey.lessThan, - BreakpointKey.greaterThan, - BreakpointKey.greaterThanOrEqual, - BreakpointKey.between, + BreakpointConstraint.at, + BreakpointConstraint.lessThan, + BreakpointConstraint.greaterThan, + BreakpointConstraint.greaterThanOrEqual, + BreakpointConstraint.between, ] } private _sortedBreakpoints: ReadonlyArray private _breakpoints: Record - private _mediaQueries: Record> + private _mediaQueries: Record> constructor(breakpoints: { [key: string]: number }) { this._breakpoints = breakpoints @@ -61,38 +64,37 @@ export class Breakpoints { ) this._mediaQueries = { - [BreakpointKey.at]: this._createBreakpointQueries( - BreakpointKey.at, + [BreakpointConstraint.at]: this._createBreakpointQueries( + BreakpointConstraint.at, this._sortedBreakpoints ), - [BreakpointKey.lessThan]: this._createBreakpointQueries( - BreakpointKey.lessThan, + [BreakpointConstraint.lessThan]: this._createBreakpointQueries( + BreakpointConstraint.lessThan, this._sortedBreakpoints.slice(1) ), - [BreakpointKey.greaterThan]: this._createBreakpointQueries( - BreakpointKey.greaterThan, + [BreakpointConstraint.greaterThan]: this._createBreakpointQueries( + BreakpointConstraint.greaterThan, this._sortedBreakpoints.slice(0, -1) ), - [BreakpointKey.greaterThanOrEqual]: this._createBreakpointQueries( - BreakpointKey.greaterThanOrEqual, + [BreakpointConstraint.greaterThanOrEqual]: this._createBreakpointQueries( + BreakpointConstraint.greaterThanOrEqual, this._sortedBreakpoints ), - [BreakpointKey.between]: this._createBreakpointQueries( - BreakpointKey.between, + [BreakpointConstraint.between]: this._createBreakpointQueries( + BreakpointConstraint.between, betweenCombinations ), } } public get sortedBreakpoints() { - return this._sortedBreakpoints as B[] + return this._sortedBreakpoints as BreakpointKey[] } public get dynamicResponsiveMediaQueries() { - return Array.from(this._mediaQueries[BreakpointKey.at].entries()).reduce( - (acc, [k, v]) => ({ ...acc, [k]: v }), - {} - ) + return Array.from( + this._mediaQueries[BreakpointConstraint.at].entries() + ).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}) } public get largestBreakpoint() { @@ -109,12 +111,12 @@ export class Breakpoints { } const throughBreakpoint = this.findBreakpointAtWidth(throughWidth) if (!throughBreakpoint || fromBreakpoint === throughBreakpoint) { - return [fromBreakpoint] as B[] + return [fromBreakpoint] as BreakpointKey[] } else { return this._sortedBreakpoints.slice( this._sortedBreakpoints.indexOf(fromBreakpoint), this._sortedBreakpoints.indexOf(throughBreakpoint) + 1 - ) as B[] + ) as BreakpointKey[] } } @@ -129,7 +131,7 @@ export class Breakpoints { } else { return width >= this._breakpoints[breakpoint] } - }) as B | undefined + }) as BreakpointKey | undefined } public toRuleSets(keys = Breakpoints.validKeys()) { @@ -138,7 +140,7 @@ export class Breakpoints { mediaQueries[query] = this._mediaQueries[query] return mediaQueries }, - {} as Record> + {} as Record> ) return Object.entries(selectedMediaQueries).reduce( @@ -201,10 +203,10 @@ export class Breakpoints { return false } - public valuesWithBreakpointProps = ( - values: T[] - ): Array> => { - type ValueBreakpoints = [T, string[]] + public valuesWithBreakpointProps = ( + values: SizeValue[] + ): Array> => { + type ValueBreakpoints = [SizeValue, string[]] const max = values.length const valueBreakpoints: ValueBreakpoints[] = [] let lastTuple: ValueBreakpoints @@ -229,7 +231,10 @@ export class Breakpoints { // prop, which unlike `between` is inclusive. props.between = [breakpoints[0], valueBreakpoints[i + 1][1][0]] } - return [value, props] as ValueBreakpointPropsTuple + return [value, props] as ValueBreakpointPropsTuple< + SizeValue, + BreakpointKey + > }) } @@ -275,7 +280,7 @@ export class Breakpoints { } private _createBreakpointQueries( - key: MediaBreakpointKey, + key: BreakpointConstraintKey, forBreakpoints: ReadonlyArray ) { return forBreakpoints.reduce>((map, breakpoint) => { diff --git a/src/Media.tsx b/src/Media.tsx index 658dd6c..f93e8d4 100644 --- a/src/Media.tsx +++ b/src/Media.tsx @@ -4,7 +4,7 @@ import React from "react" import { createResponsiveComponents } from "./DynamicResponsive" import { MediaQueries } from "./MediaQueries" import { intersection, propKey, createClassName } from "./Utils" -import { BreakpointKey } from "./Breakpoints" +import { BreakpointConstraint } from "./Breakpoints" /** * A render prop that can be used to render a different container element than @@ -19,7 +19,7 @@ export type RenderProp = ( // TODO: All of these props should be mutually exclusive. Using a union should // probably be made possible by https://github.com/Microsoft/TypeScript/pull/27408. -export interface MediaBreakpointProps { +export interface MediaBreakpointProps { /** * Children will only be shown if the viewport matches the specified * breakpoint. That is, a viewport width that’s higher than the configured @@ -43,7 +43,7 @@ export interface MediaBreakpointProps { ``` * */ - at?: B + at?: BreakpointKey /** * Children will only be shown if the viewport is smaller than the specified @@ -63,7 +63,7 @@ export interface MediaBreakpointProps { ``` * */ - lessThan?: B + lessThan?: BreakpointKey /** * Children will only be shown if the viewport is greater than the specified @@ -83,7 +83,7 @@ export interface MediaBreakpointProps { ``` * */ - greaterThan?: B + greaterThan?: BreakpointKey /** * Children will only be shown if the viewport is greater or equal to the @@ -106,7 +106,7 @@ export interface MediaBreakpointProps { ``` * */ - greaterThanOrEqual?: B + greaterThanOrEqual?: BreakpointKey /** * Children will only be shown if the viewport is between the specified @@ -127,10 +127,11 @@ export interface MediaBreakpointProps { ``` * */ - between?: [B, B] + between?: [BreakpointKey, BreakpointKey] } -export interface MediaProps extends MediaBreakpointProps { +export interface MediaProps + extends MediaBreakpointProps { /** * Children will only be shown if the interaction query matches. * @@ -144,7 +145,7 @@ export interface MediaProps extends MediaBreakpointProps { ohai ``` */ - interaction?: I + interaction?: Interaction /** * The component(s) that should conditionally be shown, depending on the media @@ -221,13 +222,13 @@ export interface CreateMediaConfig { interactions?: { [key: string]: string } } -export interface CreateMediaResults { +export interface CreateMediaResults { /** * The React component that you use throughout your application. * * @see {@link MediaBreakpointProps} */ - Media: React.ComponentType> + Media: React.ComponentType> /** * The React Context provider component that you use to constrain rendering of @@ -235,18 +236,20 @@ export interface CreateMediaResults { * * @see {@link MediaContextProviderProps} */ - MediaContextProvider: React.ComponentType> + MediaContextProvider: React.ComponentType< + MediaContextProviderProps + > /** * Generates a set of CSS rules that you should include in your application’s * styling to enable the hiding behaviour of your `Media` component uses. */ - createMediaStyle(breakpointKeys?: BreakpointKey[]): string + createMediaStyle(breakpointKeys?: BreakpointConstraint[]): string /** * A list of your application’s breakpoints sorted from small to large. */ - SortedBreakpoints: B[] + SortedBreakpoints: BreakpointKey[] /** * Creates a list of your application’s breakpoints that support the given @@ -255,12 +258,12 @@ export interface CreateMediaResults { findBreakpointsForWidths( fromWidth: number, throughWidth: number - ): B[] | undefined + ): BreakpointKey[] | undefined /** * Finds the breakpoint that matches the given width. */ - findBreakpointAtWidth(width: number): B | undefined + findBreakpointAtWidth(width: number): BreakpointKey | undefined /** * Maps a list of values for various breakpoints to props that can be used @@ -270,7 +273,9 @@ export interface CreateMediaResults { * less values are specified than the number of breakpoints your application * has, the last value will be applied to all subsequent breakpoints. */ - valuesWithBreakpointProps(values: T[]): Array<[T, MediaBreakpointProps]> + valuesWithBreakpointProps( + values: SizeValue[] + ): Array<[SizeValue, MediaBreakpointProps]> } /** @@ -304,25 +309,25 @@ export interface CreateMediaResults { * */ export function createMedia< - C extends CreateMediaConfig, - B extends keyof C["breakpoints"], - I extends keyof C["interactions"] ->(config: C): CreateMediaResults { - const mediaQueries = new MediaQueries( + MediaConfig extends CreateMediaConfig, + BreakpointKey extends keyof MediaConfig["breakpoints"], + Interaction extends keyof MediaConfig["interactions"] +>(config: MediaConfig): CreateMediaResults { + const mediaQueries = new MediaQueries( config.breakpoints, config.interactions || {} ) const DynamicResponsive = createResponsiveComponents() - const MediaContext = React.createContext>({}) + const MediaContext = React.createContext< + MediaContextProviderProps + >({}) MediaContext.displayName = "Media.Context" - const MediaContextProvider: React.SFC> = ({ - disableDynamicMediaQueries, - onlyMatch, - children, - }) => { + const MediaContextProvider: React.SFC< + MediaContextProviderProps + > = ({ disableDynamicMediaQueries, onlyMatch, children }) => { if (disableDynamicMediaQueries) { return ( > { + const Media = class extends React.Component< + MediaProps + > { constructor(props) { super(props) validateProps(props) diff --git a/src/MediaQueries.ts b/src/MediaQueries.ts index e3e8574..4ba1733 100644 --- a/src/MediaQueries.ts +++ b/src/MediaQueries.ts @@ -1,4 +1,4 @@ -import { Breakpoints, BreakpointKey } from "./Breakpoints" +import { Breakpoints, BreakpointConstraint } from "./Breakpoints" import { Interactions } from "./Interactions" import { intersection } from "./Utils" import { MediaBreakpointProps } from "./Media" @@ -28,7 +28,7 @@ export class MediaQueries { return this._breakpoints } - public toStyle = (breakpointKeys?: BreakpointKey[]) => { + public toStyle = (breakpointKeys?: BreakpointConstraint[]) => { return [ // Don’t add any size to the layout ".fresnel-container{margin:0;padding:0;}", diff --git a/src/Utils.ts b/src/Utils.ts index d68ad12..ebe6de9 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -1,11 +1,11 @@ import { MediaBreakpointProps } from "./Media" -import { MediaBreakpointKey } from "./Breakpoints" +import { BreakpointConstraintKey } from "./Breakpoints" /** * Extracts the single breakpoint prop from the props object. */ export function propKey(breakpointProps: MediaBreakpointProps) { - return Object.keys(breakpointProps)[0] as MediaBreakpointKey + return Object.keys(breakpointProps)[0] as BreakpointConstraintKey } /** diff --git a/src/__test__/Media.test.tsx b/src/__test__/Media.test.tsx index c5dced7..0a1692c 100644 --- a/src/__test__/Media.test.tsx +++ b/src/__test__/Media.test.tsx @@ -4,7 +4,7 @@ import React from "react" import renderer, { ReactTestRendererJSON } from "react-test-renderer" import { injectGlobal } from "styled-components" import { createMedia } from "../Media" -import { BreakpointKey } from "../Breakpoints" +import { BreakpointConstraint } from "../Breakpoints" import { MediaQueries } from "../MediaQueries" import ReactDOMServer from "react-dom/server" import ReactDOM from "react-dom" @@ -152,8 +152,8 @@ describe("Media", () => { expect(defaultMediaStyles).toContain(".fresnel-between-small-large") const subsetMediaStyles = createMediaStyle([ - BreakpointKey.at, - BreakpointKey.greaterThan, + BreakpointConstraint.at, + BreakpointConstraint.greaterThan, ]) expect(subsetMediaStyles).not.toContain(".fresnel-between-small-large") expect(subsetMediaStyles).toContain(".fresnel-at-extra-small") diff --git a/src/index.tsx b/src/index.tsx index fe564a5..260c34e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,2 +1,2 @@ export { createMedia } from "./Media" -export { BreakpointKey } from "./Breakpoints" +export { BreakpointConstraint as BreakpointKey } from "./Breakpoints"