-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 143891a
Showing
5 changed files
with
159 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
lib/ | ||
node_modules/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
src/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
redux-mediaquery | ||
=== | ||
|
||
Intro | ||
--- | ||
This is an ActionCreator for Redux that makes CSS mediaqueries (and more) available in the store. This allows you to declaratively make responsive layouts. | ||
|
||
It is very small, without any dependencies, except that the reducer requires Object.assign(). | ||
|
||
Use Cases | ||
--- | ||
* Complement CSS, rendering fully different components depending on screen size instead of just showing/hiding parts of the application | ||
* Update measuring components when screen size changes | ||
* responsive images | ||
* flag server-side rendering | ||
* TODO code examples | ||
|
||
How to use | ||
--- | ||
* add reducer or use own | ||
* configure queries | ||
* write them so falsy is the default, for server side rendering or in case matchMedia doesn't exist | ||
* connect components to store | ||
* sit back and relax 🏝 | ||
|
||
Browser Support | ||
--- | ||
For innerWidth/innerHeight, IE9 is sufficient. For the mediaqueries, this relies on matchMedia() support in the browser, and thus requires Internet Explorer 10+. | ||
|
||
<table> | ||
<tr><th>Chrome<th>Firefox (Gecko)<th>Internet Explorer<th>Opera<th>Safari | ||
<tr><td>9<td>6.0 (6.0)<td>10<td>12.1<td>5.1 | ||
<tr><th>Android <th>Firefox Mobile (Gecko) <th>IE Mobile <th>Opera Mobile<th>Safari Mobile | ||
<tr><td>3.0<td>6.0 (6.0)<td>No support<td>12.1<td>5 | ||
</table> | ||
|
||
**Object.assign() needs to be polyfilled if missing**. (It is probably already available, through your JSX build) | ||
|
||
Ideas for future development | ||
--- | ||
* uglify build | ||
* unlisten call | ||
* tests, thoughts on how to test this would be appreciated | ||
* stable API once more feedback from community | ||
* allow use without redux-thunk? | ||
* other special measurements? e.g. "is actual phone", "has touch", … | ||
* a collection of breakpoints/queries? | ||
* server side helpers for converting from user agent string to redux actions | ||
* demo page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
{ | ||
"name": "redux-mediaquery", | ||
"version": "0.9.0", | ||
"description": "Manage your responsive layout via Redux", | ||
"main": "lib/media-query-tracker.js", | ||
"scripts": { | ||
"build": "babel src --presets babel-preset-es2015 --out-dir lib", | ||
"prepublish": "npm run build" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Yaska/redux-mediaquery.git" | ||
}, | ||
"keywords": [ | ||
"redux", | ||
"mediaquery", | ||
"responsive", | ||
"react" | ||
], | ||
"author": "Wout Mertens", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/Yaska/redux-mediaquery/issues" | ||
}, | ||
"homepage": "https://github.com/Yaska/redux-mediaquery#readme", | ||
"devDependencies": { | ||
"babel-cli": "^6.9.0", | ||
"babel-preset-es2015": "^6.9.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const listeners = [] | ||
export const MEDIA_CHANGED = 'rdx-mqt/MEDIA_CHANGED' | ||
|
||
// Reducer | ||
export function reducer(state = {}, action) { | ||
switch (action.type) { | ||
case c.MEDIA_CHANGED: | ||
return Object.assign({}, state, action.data) | ||
default: | ||
return state | ||
} | ||
} | ||
|
||
// Actions | ||
export function mediaChanged(data) { | ||
return { | ||
type: MEDIA_CHANGED, | ||
data | ||
} | ||
} | ||
|
||
let trackInnerWidth = false | ||
let trackInnerHeight = false | ||
let onResize | ||
const getSizes = (data) => { | ||
if (trackInnerWidth) { | ||
data.innerWidth = global.innerWidth | ||
} | ||
if (trackInnerHeight) { | ||
data.innerHeight = global.innerHeight | ||
} | ||
} | ||
const makeOnResize = dispatch => () => { | ||
const data = {} | ||
getSizes(data) | ||
dispatch(mediaChanged(data)) | ||
} | ||
function trackMediaQuery(label, query, dispatch, initData) { | ||
// special queries | ||
if (label === 'innerWidth' || label === 'innerHeight') { | ||
if (label === 'innerWidth') { | ||
trackInnerWidth = true | ||
} | ||
if (label === 'innerHeight') { | ||
trackInnerHeight = true | ||
} | ||
if (!onResize) { | ||
onResize = makeOnResize(dispatch) | ||
if (global.addEventListener) { | ||
global.addEventListener('resize', onResize, true) | ||
} | ||
} | ||
getSizes(initData) | ||
} | ||
|
||
const mq = global.matchMedia(query) | ||
|
||
const listener = () => dispatch(mediaChange({ | ||
[label]: mq.matches | ||
})) | ||
mq.addListener(listener) | ||
|
||
initData[label] = mq.matches | ||
return | ||
} | ||
|
||
export function mediaQueryTracker(queries) { | ||
return dispatch => { | ||
const initData = {} | ||
if (global.matchMedia) { | ||
for (const label in queries) { | ||
trackMediaQuery(label, queries[label], dispatch, initData) | ||
} | ||
dispatch(mediaChange(initData)) | ||
} | ||
} | ||
} |