Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch to matchmedia module for client/server abstraction #11

Merged
merged 5 commits into from
Feb 27, 2015
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
111 changes: 77 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,39 @@ This module is pretty straightforward: You specify a set of requirements, and th

## Usage

A mq element functions like any other React component, which means you can nest them and do all the normal jazz.
A Mq element functions like any other React component, which means you can nest them and do all the normal jazz.

### Using CSS Media Queries

```js
var mq = require('react-responsive');
```jsx
var Mq = require('react-responsive');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MQ? MediaQuery?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dig MediaQuery, will update


var A = React.createClass({
render: function(){
return (
<div>
<div>Device Test!</div>
<mq query='(min-device-width: 1224px)'>
<Mq query='(min-device-width: 1224px)'>
<div>You are a desktop or laptop</div>
<mq query='(min-device-width: 1824px)'>
<Mq query='(min-device-width: 1824px)'>
<div>You also have a huge screen</div>
</mq>
<mq query='(max-width: 1224px)'>
</Mq>
<Mq query='(max-width: 1224px)'>
<div>You are sized like a tablet or mobile phone though</div>
</mq>
</mq>
<mq query='(max-device-width: 1224px)'>
</Mq>
</Mq>
<Mq query='(max-device-width: 1224px)'>
<div>You are a tablet or mobile phone</div>
</mq>
<mq query='(orientation: portrait)'>
</Mq>
<Mq query='(orientation: portrait)'>
<div>You are portrait</div>
</mq>
<mq query='(orientation: landscape)'>
</Mq>
<Mq query='(orientation: landscape)'>
<div>You are landscape</div>
</mq>
<mq query='(min-resolution: 2dppx)'>
</Mq>
<Mq query='(min-resolution: 2dppx)'>
<div>You are retina</div>
</mq>
</Mq>
</div>
);
}
Expand All @@ -71,35 +71,78 @@ For a list of all possible shorthands and value types see https://github.com/wea
Any numbers given as a shorthand will be expanded to px (`1234` will become `'1234px'`)


```js
var mq = require('react-responsive');
```jsx
var Mq = require('react-responsive');

var A = React.createClass({
render: function(){
return (
<div>
<div>Device Test!</div>
<mq minDeviceWidth={1224}>
<Mq minDeviceWidth={1224}>
<div>You are a desktop or laptop</div>
<mq minDeviceWidth={1824}>
<Mq minDeviceWidth={1824}>
<div>You also have a huge screen</div>
</mq>
<mq maxWidth={1224}>
</Mq>
<Mq maxWidth={1224}>
<div>You are sized like a tablet or mobile phone though</div>
</mq>
</mq>
<mq maxDeviceWidth={1224}>
</Mq>
</Mq>
<Mq maxDeviceWidth={1224}>
<div>You are a tablet or mobile phone</div>
</mq>
<mq orientation='portrait'>
</Mq>
<Mq orientation='portrait'>
<div>You are portrait</div>
</mq>
<mq orientation='landscape'>
</Mq>
<Mq orientation='landscape'>
<div>You are landscape</div>
</mq>
<mq minResolution='2dppx'>
</Mq>
<Mq minResolution='2dppx'>
<div>You are retina</div>
</mq>
</Mq>
</div>
);
}
});
```

### Server rendering

Server rendering can be done by passing static values through the `values` property.

The values property can contain `orientation`, `scan`, `aspectRatio`, `deviceAspectRatio`,
`height`, `deviceHeight`, `width`, `deviceWidth`, `color`, `colorIndex`, `monochrome`,
and `resolution` to be matched against the media query.

```jsx
var Mq = require('react-responsive');

var A = React.createClass({
render: function(){
return (
<div>
<div>Device Test!</div>
<Mq minDeviceWidth={1224} values={{deviceWidth: 1600}}>
<div>You are a desktop or laptop</div>
<Mq minDeviceWidth={1824}>
<div>You also have a huge screen</div>
</Mq>
<Mq maxWidth={1224}>
<div>You are sized like a tablet or mobile phone though</div>
</Mq>
</Mq>
<Mq maxDeviceWidth={1224}>
<div>You are a tablet or mobile phone</div>
</Mq>
<Mq orientation='portrait'>
<div>You are portrait</div>
</Mq>
<Mq orientation='landscape'>
<div>You are landscape</div>
</Mq>
<Mq minResolution='2dppx'>
<div>You are retina</div>
</Mq>
</div>
);
}
Expand Down Expand Up @@ -145,4 +188,4 @@ Pretty much everything. Check out these polyfills:

[downloads-image]: http://img.shields.io/npm/dm/react-responsive.svg
[npm-url]: https://npmjs.org/package/react-responsive
[npm-image]: http://img.shields.io/npm/v/react-responsive.svg
[npm-image]: http://img.shields.io/npm/v/react-responsive.svg
20 changes: 19 additions & 1 deletion gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ var sampleBundler = watchify(browserify('./samples/sandbox/src/index.jsx', {
}));
sampleBundler.transform(reactify);

var staticSampleBundler = watchify(browserify('./samples/static/src/index.jsx', {
cache: bundleCache,
packageCache: pkgCache,
fullPaths: true,
standalone: 'sample',
debug: true
}));
staticSampleBundler.transform(reactify);

gulp.task('watch', function(){
bundler.on('update', function(){
gulp.start('js');
Expand Down Expand Up @@ -79,11 +88,20 @@ gulp.task('samples', function(){
.pipe(gulp.dest('samples/sandbox/dist'))
.pipe(lr());

var browserifyStream2 = staticSampleBundler.bundle()
// browserify -> gulp transfer
.pipe(source('index.js'))
.pipe(buffer())
.pipe(cached('index'))
.pipe(sourcemaps.init({loadMaps: true}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('samples/static/dist'));

var staticStream = gulp.src(['samples/sandbox/src/**/*', '!samples/sandbox/src/**/*.js'])
.pipe(cached('static-samples'))
.pipe(gulp.dest('samples/sandbox/dist'));

return merge(staticStream, browserifyStream);
return merge(staticStream, browserifyStream, browserifyStream2);
});

gulp.task('sample-server', function(cb){
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
],
"dependencies": {
"lodash.omit": "^3.0.0",
"matchmedia": "^0.1.1",
"object-assign": "^2.0.0"
},
"peerDependencies": {
Expand All @@ -43,7 +44,7 @@
"jshint-stylish": "^0.4.0",
"merge-stream": "^0.1.5",
"mocha": "^1.20.1",
"reactify": "^0.14.0",
"reactify": "^1.0.0",
"should": "^4.0.4",
"vinyl-buffer": "0.0.0",
"vinyl-source-stream": "^0.1.1",
Expand Down
33 changes: 16 additions & 17 deletions samples/sandbox/src/index.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
/** @jsx React.DOM */
/* global document, window */

'use strict';

var mq = require('../../../src');
var Mq = require('../../../src');
var React = require('react');
window.React = React; // for dev

Expand All @@ -13,31 +12,31 @@ var App = React.createClass({
return (
<div>
<div>Device Test!</div>
<mq minDeviceWidth={1224}>
<Mq minDeviceWidth={1224}>
<div>You are a desktop or laptop</div>
<mq minDeviceWidth={1824}>
<Mq minDeviceWidth={1824}>
<div>You also have a huge screen</div>
</mq>
<mq maxWidth={1224}>
</Mq>
<Mq maxWidth={1224}>
<div>You are sized like a tablet or mobile phone though</div>
</mq>
</mq>
<mq maxDeviceWidth={1224}>
</Mq>
</Mq>
<Mq maxDeviceWidth={1224}>
<div>You are a tablet or mobile phone</div>
</mq>
</Mq>

<mq orientation='portrait'>
<Mq orientation='portrait'>
<div>You are portrait</div>
</mq>
<mq orientation='landscape'>
</Mq>
<Mq orientation='landscape'>
<div>You are landscape</div>
</mq>
<mq minResolution='2dppx'>
</Mq>
<Mq minResolution='2dppx'>
<div>You are retina</div>
</mq>
</Mq>
</div>
);
}
});

React.renderComponent(App(), document.body);
React.renderComponent(App(), document.body);
39 changes: 39 additions & 0 deletions samples/static/src/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

var Mq = require('../../../src');
var React = require('react');

var App = React.createClass({
displayName: 'demo',
render: function(){
return (
<div>
<div>Device Test!</div>
<Mq minDeviceWidth={1224} values={{deviceWidth: 1230}}>
<div>You are a desktop or laptop</div>
<Mq minDeviceWidth={1824}>
<div>You also have a huge screen</div>
</Mq>
<Mq maxWidth={1224}>
<div>You are sized like a tablet or mobile phone though</div>
</Mq>
</Mq>
<Mq maxDeviceWidth={1224}>
<div>You are a tablet or mobile phone</div>
</Mq>

<Mq orientation='portrait'>
<div>You are portrait</div>
</Mq>
<Mq orientation='landscape'>
<div>You are landscape</div>
</Mq>
<Mq minResolution='2dppx'>
<div>You are retina</div>
</Mq>
</div>
);
}
});

console.log(React.renderToString(<App />));
25 changes: 19 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

var React = require('react');
var omit = require('lodash.omit');
var matchMedia = require('matchmedia');
var hyphenate = require('react/lib/hyphenateStyleName');
var mediaQuery = require('./mediaQuery');
var toQuery = require('./toQuery');
var matchMedia = typeof window !== 'undefined' ? window.matchMedia : null;

var defaultTypes = {
component: React.PropTypes.func,
query: React.PropTypes.string
component: React.PropTypes.node,
query: React.PropTypes.string,
values: React.PropTypes.shape(mediaQuery.matchers)
};
var mediaKeys = Object.keys(mediaQuery.all);
var excludedQueryKeys = Object.keys(defaultTypes);
Expand All @@ -21,7 +23,8 @@ var mq = React.createClass({

getDefaultProps: function(){
return {
component: React.DOM.div
component: 'div',
values: {}
};
},

Expand All @@ -40,6 +43,7 @@ var mq = React.createClass({
},

updateQuery: function(props){
var values;
if (props.query) {
this.query = props.query;
} else {
Expand All @@ -49,7 +53,16 @@ var mq = React.createClass({
if (!this.query) {
throw new Error('Invalid or missing MediaQuery!');
}
this._mql = matchMedia(this.query);

if (props.values) {
values = Object.keys(props.values)
.reduce(function(result, key){
result[hyphenate(key)] = props.values[key];
return result;
}, {});
}

this._mql = matchMedia(this.query, values);
this._mql.addListener(this.updateMatches);
this.updateMatches();
},
Expand All @@ -72,7 +85,7 @@ var mq = React.createClass({
return null;
}
var props = omit(this.props, excludedPropKeys);
return this.props.component(props, this.props.children);
return React.createElement(this.props.component, props, this.props.children);
}
});

Expand Down