Skip to content

Commit

Permalink
Port over media-query-match package
Browse files Browse the repository at this point in the history
  • Loading branch information
craigpalermo committed Dec 6, 2020
1 parent 0afd1e0 commit 1a7400c
Show file tree
Hide file tree
Showing 17 changed files with 5,495 additions and 4,216 deletions.
9,184 changes: 4,971 additions & 4,213 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions packages/media-query-match/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
**/.rush/*
**/node_modules/*

**/coverage/*

**/dist/*
4 changes: 4 additions & 0 deletions packages/media-query-match/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
extends: ['@priceline', '@priceline/eslint-config/jsx-a11y'],
parserOptions: { tsconfigRootDir: __dirname },
}
15 changes: 15 additions & 0 deletions packages/media-query-match/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# pcln-media-query-match

MediaQueryMatch is a React component that is used to conditionally render children based on if a media query matches or not.

Supported Breakpoints:

| Name | Width in `em`s | Width in `px` |
| ---- | -------------- | ------------- |
| xs | 20em | 320px |
| sm | 32em | 512px |
| md | 40em | 640px |
| lg | 48em | 768px |
| xl | 64em | 1024px |
| xxl | 80em | 1280px |

1 change: 1 addition & 0 deletions packages/media-query-match/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = { presets: ['@priceline'] }
10 changes: 10 additions & 0 deletions packages/media-query-match/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
collectCoverageFrom: [
'<rootDir>/src/**/*.js',
'!<rootDir>/src/**/*.stories.js',
],
moduleDirectories: ['node_modules', 'test'],
reporters: ['jest-standard-reporter'],
setupFilesAfterEnv: ['./test/jest.setup.js'],
testMatch: ['<rootDir>/src/**/*.spec.js'],
}
70 changes: 70 additions & 0 deletions packages/media-query-match/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"name": "pcln-media-query-match",
"version": "1.0.0",
"description": "Conditionally render React components based on media queries",
"scripts": {
"start": "start-storybook",
"build:babel:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs babel ./src --ignore '**/*.stories.js,**/*.spec.js' --out-dir ./dist/cjs",
"build:babel:esm": "cross-env NODE_ENV=production BABEL_ENV=esm babel ./src --ignore '**/*.stories.js,**/*.spec.js' --out-dir ./dist/esm",
"build:babel:es": "cross-env NODE_ENV=production BABEL_ENV=es babel ./src --ignore '**/*.stories.js,**/*.spec.js' --out-dir ./dist/es",
"build": "run-p build:babel:*",
"test": "jest",
"test:ci": "jest --runInBand",
"test:changed": "jest -o",
"test:watch": "jest --watch",
"postpublish": "slack-component-publish",
"lint": "eslint ."
},
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"license": "MIT",
"author": "Steven Dalonzo",
"files": [
"dist/"
],
"devDependencies": {
"@babel/cli": "^7.12.1",
"@babel/core": "^7.12.3",
"@babel/runtime": "^7.12.3",
"@babel/plugin-transform-react-jsx": "^7.12.5",
"@priceline/babel-preset": "^0.0.1",
"@priceline/eslint-config": "^0.0.1",
"@compositor/kit": "^1.0.47",
"@mdx-js/loader": "^1.5.7",
"@storybook/addon-actions": "^5.3.14",
"@storybook/react": "^5.3.14",
"@testing-library/jest-dom": "^5.11.5",
"@testing-library/react": "^9.5.0",
"acorn": "^7.1.0",
"babel-jest": "^26.3.0",
"babel-loader": "^8.1.0",
"cross-env": "^7.0.2",
"jest": "^26.6.1",
"jest-bamboo-reporter": "^1.2.1",
"jest-standard-reporter": "^1.1.1",
"jest-styled-components": "^6.3.4",
"lodash": "^4.17.20",
"pcln-design-system": "^4.1.2",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-responsive": "^6.1.2",
"rimraf": "^3.0.2",
"storybook-addon-deps": "^1.0.12",
"styled-components": "^4.4.1",
"eslint": "^7.13.0",
"npm-run-all": "^4.1.5"
},
"peerDependencies": {
"@babel/runtime": "^7.8.4",
"lodash": ">=4.17.15",
"prop-types": "^15.7.2",
"react": ">=16.9.0",
"react-dom": ">=16.9.0",
"react-responsive": "^6.1.1"
},
"engines": {
"npm": ">=6.4.1",
"node": ">=10.15.3"
}
}
65 changes: 65 additions & 0 deletions packages/media-query-match/src/MediaQueryMatch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import React from 'react'
import PropTypes from 'prop-types'
import Responsive from 'react-responsive'

const matchers = {
xs: '20em',
sm: '32em',
md: '40em',
lg: '48em',
xl: '64em',
xxl: '80em',
}

/**
* MediaQueryMatch is a React component that is used to conditionally render provided children based on the
* result of evaluating media queries.
*
* Supported breakpoints:
*
* | Name | Width in `em` | Width in `px` |
* | :--------------- | :----------: | :------------------: |
* | `xs` | `20em` | `320px` |
* | `sm` | `32em` | `512px` |
* | `md` | `40em` | `640px` |
* | `lg` | `48em` | `768px` |
* | `xl` | `64em` | `1024px` |
* | `xxl` | `80em` | `1280px` |
*/
const MediaQueryMatch = ({ minWidth, maxWidth, ignore, children, ...props }) => {
if (ignore) return children

if (!minWidth && !maxWidth) {
return children
}

const minBreakpoint = minWidth && matchers[minWidth]
const maxBreakpoint = maxWidth && matchers[maxWidth]
const transFormedMaxBreakPoint = maxBreakpoint && `${parseInt(maxBreakpoint) - 0.01}em`

return (
<Responsive minWidth={minBreakpoint} maxWidth={transFormedMaxBreakPoint} {...props}>
{(matchesQuery) => matchesQuery && children}
</Responsive>
)
}

MediaQueryMatch.propTypes = {
/** minimum width to mount the children */
minWidth: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl', 'xxl']),

/** maximum width to mount the children */
maxWidth: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl', 'xxl']),

/** if truthy, children will render regardless of match status. useful for SETI tests */
ignore: PropTypes.bool,

/** conditionally rendered react children */
children: PropTypes.node,
}

MediaQueryMatch.defaultProps = {
children: null,
}

export default MediaQueryMatch
139 changes: 139 additions & 0 deletions packages/media-query-match/src/MediaQueryMatch.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import React from 'react'

import { render } from '../test/react-testing'

import MediaQueryMatch from '.'

const targetNode = <span>TARGET</span>

describe('MediaQueryMatch', () => {
describe('minWidth - smaller than xs', () => {
test('matches', () => {
const { getByText } = render(
<MediaQueryMatch maxWidth='xs' values={{ width: 319 }}>
{targetNode}
</MediaQueryMatch>
)

expect(getByText('TARGET')).toBeTruthy()
})

it('should render children when not provided a minWidth or maxWidth', () => {
const { getByText } = render(<MediaQueryMatch>{targetNode}</MediaQueryMatch>)

expect(getByText('TARGET')).toBeTruthy()
})

test('does not match', () => {
const { queryByText } = render(
<MediaQueryMatch maxWidth='xs' values={{ width: 320 }}>
{targetNode}
</MediaQueryMatch>
)

expect(queryByText('TARGET')).toBeFalsy()
})
})

describe('maxWidth - mobile', () => {
test('matches', () => {
const { getByText } = render(
<MediaQueryMatch maxWidth='md' values={{ width: 639 }}>
{targetNode}
</MediaQueryMatch>
)

expect(getByText('TARGET')).toBeTruthy()
})

test('does not match', () => {
const { queryByText } = render(
<MediaQueryMatch maxWidth='md' values={{ width: 640 }}>
{targetNode}
</MediaQueryMatch>
)

expect(queryByText('TARGET')).toBeFalsy()
})
})

describe('minWidth and maxWidth - slim sidebar', () => {
test('does not match - smaller', () => {
const { queryByText } = render(
<MediaQueryMatch minWidth='xl' maxWidth='xxl' values={{ width: 1000 }}>
{targetNode}
</MediaQueryMatch>
)

expect(queryByText('TARGET')).toBeFalsy()
})

test('matches', () => {
const { getByText } = render(
<MediaQueryMatch minWidth='xl' maxWidth='xxl' values={{ width: 1120 }}>
{targetNode}
</MediaQueryMatch>
)

expect(getByText('TARGET')).toBeTruthy()
})

test('does not match - larger', () => {
const { queryByText } = render(
<MediaQueryMatch minWidth='xl' maxWidth='xxl' values={{ width: 1280 }}>
{targetNode}
</MediaQueryMatch>
)

expect(queryByText('TARGET')).toBeFalsy()
})
})

describe('maxWidth - desktop, ignore', () => {
test('matches, no ignore', () => {
const { getByText } = render(
<MediaQueryMatch maxWidth='xxl' values={{ width: 1000 }}>
{targetNode}
</MediaQueryMatch>
)

expect(getByText('TARGET')).toBeTruthy()
})

test('does not match, no ignore', () => {
const { queryByText } = render(
<MediaQueryMatch maxWidth='xxl' values={{ width: 1600 }}>
{targetNode}
</MediaQueryMatch>
)

expect(queryByText('TARGET')).toBeFalsy()
})

test('matches, ignore', () => {
const { getByText } = render(
<MediaQueryMatch maxWidth='xxl' ignore values={{ width: 1000 }}>
{targetNode}
</MediaQueryMatch>
)

expect(getByText('TARGET')).toBeTruthy()
})

test('matches, ignore, no children', () => {
const { queryByText } = render(<MediaQueryMatch maxWidth='xxl' ignore values={{ width: 1000 }} />)

expect(queryByText('TARGET')).toBeFalsy()
})

test('does not match, ignore', () => {
const { getByText } = render(
<MediaQueryMatch maxWidth='xxl' ignore values={{ width: 1600 }}>
{targetNode}
</MediaQueryMatch>
)

expect(getByText('TARGET')).toBeTruthy()
})
})
})
Loading

0 comments on commit 1a7400c

Please sign in to comment.