├── .gitignore ├── .jscsrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── docs ├── components │ ├── common │ │ ├── Code.jsx │ │ ├── Markdown.jsx │ │ └── MarkdownTitle.jsx │ ├── home │ │ ├── Home.jsx │ │ ├── HomeBody.jsx │ │ ├── HomeFeature.jsx │ │ ├── HomeHeader.jsx │ │ ├── HomeSidebar.jsx │ │ └── HomeSidebarItem.jsx │ └── layout │ │ ├── Container.jsx │ │ ├── Grid.jsx │ │ └── Root.jsx ├── documentation │ ├── 01-about.md │ ├── 02-usage.md │ ├── 02.01-root.md │ ├── 02.02-set-types.md │ ├── 03-contexts.md │ ├── adBlock.md │ ├── browser.md │ ├── browserVersion.md │ ├── density.md │ ├── focus.md │ ├── height.md │ ├── index.js │ ├── language.md │ ├── os.md │ ├── pointer.md │ ├── scroll.md │ └── width.md ├── helpers │ └── markdown.js ├── images │ ├── react-context-bg.jpg │ └── react-context-logo.png └── index.js ├── examples ├── Child.jsx └── Root.jsx ├── favicon.ico ├── gulpfile.js ├── index.html ├── modules └── react-material-design │ ├── index.js │ └── src │ └── components │ ├── Raised.jsx │ └── Tile.jsx ├── package.json └── src └── context.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "airbnb", 3 | "excludeFiles": ["build/**", "node_modules/**"], 4 | "disallowQuotedKeysInObjects": null, 5 | "validateQuoteMarks": null, 6 | "requireSemicolons": false, 7 | "disallowSemicolons": true 8 | } 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.0.3 (2 February 2016) 2 | 3 | - Fix "Can't find variable: nameOffset" ([#10](https://github.com/casesandberg/react-context/issues/10)) 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 case 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [React Context](http://casesandberg.github.io/react-context/) 2 | 3 | * **Engagement Properties** - AdBlock and Focus 4 | * **Display Properties** - Density, Scroll, Width and Height 5 | * **Device Properties** - Language, OS, Browser and Browser Version 6 | 7 | ```js 8 | var React = require('react'); 9 | var context = require('react-context'); 10 | 11 | var Component = React.createClass({ 12 | 13 | // subscribe to all the contextTypes 14 | contextTypes: context.subscribe(['os']), 15 | 16 | render() { 17 | var downloadLink; 18 | 19 | switch (this.state.os) { 20 | case 'Windows': 21 | downloadLink = 'http://some.url/downloads/App.exe'; 22 | break; 23 | case 'Mac': 24 | downloadLink = 'http://some.url/downloads/App.app'; 25 | break; 26 | case 'Android': 27 | downloadLink = 'https://play.google.com/store/apps/details?id=com.app.some'; 28 | break; 29 | case 'iOS': 30 | downloadLink = 'https://itunes.apple.com/us/app/someapp/id12345678'; 31 | break; 32 | default: 33 | downloadLink = 'http://some.url/downloads/'; 34 | break; 35 | } 36 | 37 | return Download App 38 | } 39 | }); 40 | ``` 41 | 42 | ## Installation & Usage 43 | 44 | ``` 45 | npm install react-context --save 46 | ``` 47 | 48 | ### Wrap Root 49 | Wrap your top-most component with `react-context`. 50 | 51 | ```js 52 | var React = require('react'); 53 | var context = require('react-context'); 54 | 55 | var Root = React.createClass({ 56 | render() { 57 | return
Root
58 | } 59 | }); 60 | 61 | module.exports = context(Root); 62 | ``` 63 | 64 | ### Set Types 65 | Pass it an array of types you want to subscribe to, or call it with no arguments to subscribe to all of them. 66 | 67 | ```javascript 68 | // Subscribe to scroll and adBlock 69 | Child.contextTypes = context.subscribe(['scroll', 'adBlock']); 70 | 71 | // Subscribe to every context 72 | Child.contextTypes = context.subscribe(); 73 | ``` 74 | -------------------------------------------------------------------------------- /docs/components/common/Code.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | var markdown = require('../../helpers/markdown'); 7 | var context = require('react-context'); 8 | 9 | var { Tile } = require('react-material-design'); 10 | 11 | 12 | 13 | class Code extends ReactCSS.Component { 14 | 15 | constructor() { 16 | super(); 17 | } 18 | 19 | classes() { 20 | return { 21 | 'default': { 22 | shortCodeBlock: { 23 | display: 'inline-block' 24 | }, 25 | shortCode: { 26 | padding: '14px 16px' 27 | }, 28 | head: { 29 | borderRadius: '2px 2px 0 0', 30 | background: '#fafafa' 31 | }, 32 | files: { 33 | display: 'inline-block' 34 | }, 35 | Files: { 36 | align: 'none', 37 | color: '#666' 38 | }, 39 | center: { 40 | fontFamily: 'Monaco', 41 | fontSize: '14px', 42 | lineHeight: '19px', 43 | color: 'rgba(0,0,0,.77)' 44 | }, 45 | numbers: { 46 | fontSize: '14px', 47 | lineHeight: '19px', 48 | display: 'inline-block', 49 | textAlign: 'right', 50 | color: 'rgba(0,0,0,.20)', 51 | userSelect: 'none', 52 | paddingLeft: '7px' 53 | }, 54 | }, 55 | 'condensed': { 56 | Tile: { 57 | condensed: true 58 | }, 59 | center: { 60 | paddingTop: '16px', 61 | paddingBottom: '16px', 62 | fontSize: '13px', 63 | lineHeight: '15px', 64 | overflowX: 'scroll' 65 | }, 66 | numbers: { 67 | paddingTop: '16px', 68 | fontSize: '13px', 69 | lineHeight: '15px' 70 | } 71 | }, 72 | 'borders': { 73 | code: { 74 | borderTop: '1px solid #eee', 75 | borderBottom: '1px solid #eee' 76 | } 77 | } 78 | }; 79 | } 80 | 81 | styles() { 82 | return this.css({ 83 | 'condensed': this.context.width < 500 84 | }); 85 | } 86 | 87 | render() { 88 | var code = markdown.getBody( this.props.file ); 89 | var args = markdown.getArgs( this.props.file ); 90 | var colorCoded = markdown.renderCode('```\n' + code + '```').trim(); 91 | var lineCount = colorCoded.split('\n').length; 92 | 93 | var lines; 94 | if (args.lineDecoration) { 95 | lines = args.lineDecoration; 96 | } else { 97 | lines = []; 98 | for (var i = 1; i < lineCount; i++) { 99 | lines.push(
{ i }
); 100 | } 101 | } 102 | 103 | return ( 104 |
105 | 106 | 122 | 123 | 124 |
125 | { lines } 126 |
127 |
128 | 136 |
137 |
138 | 139 | 140 | 141 |
142 | ); 143 | } 144 | } 145 | 146 | Code.contextTypes = context.subscribe(['width']); 147 | 148 | module.exports = Code 149 | -------------------------------------------------------------------------------- /docs/components/common/Markdown.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | var markdown = require('../../helpers/markdown'); 7 | 8 | var Code = require('./Code'); 9 | 10 | 11 | 12 | module.exports = class Markdown extends ReactCSS.Component { 13 | 14 | classes() { 15 | return { 16 | 'default': { 17 | markdown: { 18 | fontSize: '17px', 19 | lineHeight: '24px', 20 | color: 'rgba(0,0,0,.47)' 21 | } 22 | } 23 | }; 24 | } 25 | 26 | shouldComponentUpdate() { 27 | return false; 28 | } 29 | 30 | render() { 31 | var children = this.props.children; 32 | 33 | var newLines = children; 34 | 35 | var codes = []; 36 | for (var i = 0; i < markdown.isCode(children).length; i++) { 37 | var codeBlock = markdown.isCode(children)[i]; 38 | newLines = newLines.replace(codeBlock[1], '|Code:' + i + '|'); 39 | codes[i] = 40 | } 41 | 42 | var markdownFile = []; 43 | for (var i = 0; i < newLines.split('\n').length; i++) { 44 | var line = newLines.split('\n')[i]; 45 | if (markdown.isCodeBlock(line)) { 46 | markdownFile.push(
{ codes[ markdown.codeNumber(line) ] }
); 47 | } else { 48 | markdownFile.push(
); 49 | } 50 | } 51 | 52 | return ( 53 |
54 | 96 | 97 | { markdownFile } 98 | 99 |
100 | ) 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /docs/components/common/MarkdownTitle.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | 7 | 8 | 9 | module.exports = class MarkdownTitle extends ReactCSS.Component { 10 | 11 | constructor(){ 12 | super(); 13 | this.state = { 14 | hover: false 15 | }; 16 | this.handleHover = this.handleHover.bind(this); 17 | } 18 | 19 | classes() { 20 | return { 21 | 'default': { 22 | link: { 23 | opacity: '0', 24 | textDecoration: 'none', 25 | fill: '#2A5881', 26 | transition: 'opacity 200ms linear' 27 | } 28 | }, 29 | 'hovered': { 30 | link: { 31 | opacity: '1' 32 | } 33 | } 34 | }; 35 | } 36 | 37 | styles() { 38 | return this.css({ 39 | 'hovered': this.state.hover 40 | }); 41 | } 42 | 43 | handleHover(e) { 44 | if (e.type === 'mouseenter') { 45 | this.setState({ hover: true }); 46 | } else if (e.type === 'mouseleave') { 47 | this.setState({ hover: false }); 48 | } 49 | } 50 | 51 | render() { 52 | var linkSvg = { 53 | __html: ` 54 | 55 | 56 | 57 | ` 58 | }; 59 | 60 | var title; 61 | if (this.props.isHeadline) { 62 | title =

{ this.props.title }

63 | } else { 64 | title =

{ this.props.title }

65 | } 66 | 67 | return ( 68 |
69 | { title } 70 |
71 | ) 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /docs/components/home/Home.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | 6 | var HomeHeader = require('./HomeHeader'); 7 | var HomeFeature = require('./HomeFeature'); 8 | var HomeBody = require('./HomeBody'); 9 | 10 | 11 | 12 | 13 | module.exports = class Home extends React.Component { 14 | 15 | render(){ 16 | return ( 17 |
18 | 19 | 20 | 21 |
22 | ) 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /docs/components/home/HomeBody.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | var context = require('react-context'); 7 | var markdown = require('../../helpers/markdown'); 8 | 9 | var Container = require('../layout/Container'); 10 | var Grid = require('../layout/Grid'); 11 | var { Raised } = require('react-material-design'); 12 | var Markdown = require('../common/Markdown'); 13 | var Code = require('../common/Code'); 14 | var MarkdownTitle = require('../common/MarkdownTitle'); 15 | var HomeSidebar = require('./HomeSidebar'); 16 | 17 | var documentation = require('../../documentation'); 18 | 19 | 20 | 21 | class HomeBody extends ReactCSS.Component { 22 | 23 | constructor() { 24 | super(); 25 | this.state = { 26 | sidebarFixed: false, 27 | visible: false, 28 | files: {} 29 | }; 30 | this.changeSelection = this.changeSelection.bind(this); 31 | this.attachSidebar = this.attachSidebar.bind(this); 32 | this.handleScroll = this.handleScroll.bind(this); 33 | } 34 | 35 | classes() { 36 | return { 37 | 'default': { 38 | body: { 39 | marginBottom: '30px' 40 | }, 41 | npm: { 42 | position: 'relative' 43 | }, 44 | star: { 45 | position: 'absolute', 46 | top: '11px', 47 | right: '-22px' 48 | }, 49 | files: { 50 | paddingBottom: '15px' 51 | }, 52 | docsWrap: { 53 | overflow: 'hidden', 54 | padding: '0 5px 5px', 55 | margin: '0 -5px' 56 | }, 57 | Docs: { 58 | radius: '0 0 2px 2px' 59 | } 60 | }, 61 | 'mobile': { 62 | star: { 63 | top: '76px' 64 | } 65 | } 66 | }; 67 | } 68 | 69 | styles() { 70 | return this.css({ 71 | 'mobile': this.context.width < 500 72 | }); 73 | } 74 | 75 | componentDidMount() { 76 | window.addEventListener('scroll', this.handleScroll, false); 77 | 78 | var domFiles = React.findDOMNode(this.refs.files) && React.findDOMNode(this.refs.files).children; 79 | 80 | if (domFiles) { 81 | var files = {}; 82 | for (var i = 0; i < domFiles.length; i++) { 83 | var file = domFiles[i]; 84 | files[file.offsetTop] = file.id; 85 | } 86 | 87 | this.setState({ files: files }); 88 | } 89 | } 90 | 91 | 92 | componentWillUnmount() { 93 | window.removeEventListener('scroll', this.handleScroll, false); 94 | } 95 | 96 | handleScroll(e) { 97 | this.changeSelection(); 98 | this.attachSidebar(); 99 | } 100 | 101 | attachSidebar() { 102 | var sidebarTop = React.findDOMNode( this.refs.homeSidebar ).getBoundingClientRect().top; 103 | 104 | if (sidebarTop <= 0 && this.state.sidebarFixed === false) { 105 | this.setState({ sidebarFixed: true }); 106 | } 107 | 108 | if (sidebarTop > 0 && this.state.sidebarFixed === true) { 109 | this.setState({ sidebarFixed: false }); 110 | } 111 | } 112 | 113 | changeSelection() { 114 | var top = document.body.scrollTop - 300; 115 | var mostVisible = ''; 116 | 117 | for (var offset in this.state.files) { 118 | if (this.state.files.hasOwnProperty(offset)) { 119 | var id = this.state.files[offset]; 120 | if (offset < top) { 121 | mostVisible = id; 122 | } 123 | } 124 | } 125 | 126 | if (mostVisible !== this.state.visible) { 127 | this.setState({ visible: mostVisible }); 128 | } 129 | } 130 | 131 | render() { 132 | 133 | var markdownFiles = []; 134 | 135 | for (var fileName in documentation) { 136 | if (documentation.hasOwnProperty(fileName)) { 137 | var file = documentation[fileName]; 138 | var args = markdown.getArgs(file); 139 | var body = markdown.getBody(file); 140 | 141 | markdownFiles.push( 142 |
143 | 144 | 148 | 149 | { body } 150 |
151 | ); 152 | } 153 | } 154 | 155 | return ( 156 |
157 | 158 | 159 |
160 | 161 |
162 |
163 | 164 |
165 |
166 | 167 |
168 | 169 |
170 | 171 |
172 | { markdownFiles } 173 |
174 | 175 |
176 |
177 |
178 |
179 |
180 | ) 181 | } 182 | } 183 | 184 | HomeBody.contextTypes = context.subscribe(['width']); 185 | 186 | module.exports = HomeBody 187 | -------------------------------------------------------------------------------- /docs/components/home/HomeFeature.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | var context = require('react-context'); 7 | 8 | var Container = require('../layout/Container'); 9 | var Grid = require('../layout/Grid'); 10 | var { Raised } = require('react-material-design'); 11 | var Code = require('../common/Code'); 12 | 13 | 14 | class HomeFeature extends ReactCSS.Component { 15 | 16 | classes() { 17 | return { 18 | 'default': { 19 | feature: { 20 | boxShadow: 'inset 0 -1px 0 0 rgba(255,255,255,.2), inset 0 1px 0 0 rgba(255,255,255,.2)', 21 | position: 'relative' 22 | }, 23 | bg: { 24 | Absolute: '1px 0 1px 0', 25 | backgroundImage: 'url("docs/images/react-context-bg.jpg")', 26 | backgroundPosition: 'center center', 27 | backgroundSize: 'cover', 28 | transition: 'all 400ms linear' 29 | }, 30 | title: { 31 | paddingTop: '100px', 32 | paddingBottom: '35px', 33 | fontSize: '40px', 34 | color: '#fff' 35 | }, 36 | Snippet: { 37 | radius: '2px 2px 0 0', 38 | background: '#EEEEEE' 39 | }, 40 | }, 41 | 'fade-out': { 42 | bg: { 43 | opacity: '0' 44 | } 45 | } 46 | }; 47 | } 48 | 49 | styles() { 50 | return this.css({ 51 | 'fade-out': this.context.focus === false 52 | }); 53 | } 54 | 55 | render() { 56 | 57 | var snippet = 58 | `this.context \= \{ 59 | adBlock: ${ this.context.adBlock && this.context.adBlock.toString() } // There is an adblocker enabled 60 | focus: ${ this.context.focus && this.context.focus.toString() } // Window is focused (click your desktop) 61 | density: ${ this.context.density }, // The screen pixel density 62 | scroll: ${ this.context.scroll } // The window scroll position 63 | width: ${ this.context.width }, // The screen width (try resizing) 64 | height: ${ this.context.height }, // The screen height (try resizing) 65 | language: '${ this.context.language }', // The language thats set 66 | os: '${ this.context.os }' // The devices operating system 67 | browser: '${ this.context.browser }' // The devices browser 68 | browserVersion: '${ this.context.browserVersion }' 69 | \} 70 | `; 71 | 72 | var bg, transition; 73 | transition = 'background 400ms linear'; 74 | if (this.context.focus) { 75 | bg = '#2A5881'; 76 | } else { 77 | bg = '#666'; 78 | } 79 | 80 | return ( 81 |
82 | 101 | 102 |
103 | 104 | 105 | 106 |
107 |
108 |
React Context
109 | 110 | 111 | 112 |
113 | 114 | 115 |
116 | ) 117 | } 118 | } 119 | 120 | 121 | HomeFeature.contextTypes = context.subscribe(); 122 | 123 | module.exports = HomeFeature 124 | -------------------------------------------------------------------------------- /docs/components/home/HomeHeader.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | 7 | var Container = require('../layout/Container'); 8 | 9 | 10 | 11 | module.exports = class HomeHeader extends ReactCSS.Component { 12 | 13 | classes() { 14 | return { 15 | 'default': { 16 | header: { 17 | height: '64px' 18 | }, 19 | logo: { 20 | padding: '20px 0', 21 | float: 'left', 22 | marginLeft: '-10px' 23 | }, 24 | icon: { 25 | width: '24px', 26 | height: '24px', 27 | backgroundImage: 'url("docs/images/react-context-logo.png")', 28 | backgroundSize: '100%' 29 | }, 30 | nav: { 31 | padding: '10px 0', 32 | float: 'right', 33 | marginRight: '-10px' 34 | }, 35 | svg: { 36 | width:'24px', 37 | height:'24px', 38 | fill: 'rgba(255,255,255,.87)', 39 | padding: '10px' 40 | } 41 | } 42 | }; 43 | } 44 | 45 | render() { 46 | return ( 47 |
48 | 49 | 62 | ) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/components/home/HomeSidebar.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | var markdown = require('../../helpers/markdown'); 7 | 8 | var { Tile } = require('react-material-design'); 9 | var HomeSidebarItem = require('./HomeSidebarItem'); 10 | 11 | 12 | 13 | module.exports = class DocsSidebar extends ReactCSS.Component { 14 | 15 | classes() { 16 | return { 17 | 'default': { 18 | sidebar: { 19 | paddingTop: '20px', 20 | position: 'relative', 21 | width: '100%', 22 | maxWidth: '130px' 23 | }, 24 | star: { 25 | display: 'none', 26 | position: 'absolute' 27 | } 28 | }, 29 | 'fixed': { 30 | sidebar: { 31 | top: '0', 32 | bottom: '0', 33 | position: 'fixed' 34 | }, 35 | star: { 36 | bottom: '30px', 37 | top: 'auto', 38 | display: 'block' 39 | } 40 | } 41 | }; 42 | } 43 | 44 | render() { 45 | 46 | var sidebarItems = []; 47 | 48 | for (var fileName in this.props.files) { 49 | if (this.props.files.hasOwnProperty(fileName)) { 50 | var file = this.props.files[fileName]; 51 | var args = markdown.getArgs(file); 52 | var sectionNumber; 53 | if (markdown.isSubSection(fileName)) { 54 | sectionNumber = fileName.split('-')[0]; 55 | } else { 56 | sectionNumber = false; 57 | } 58 | 59 | sidebarItems.push( 60 | 66 | ); 67 | } 68 | } 69 | 70 | return ( 71 |
72 | 73 |
74 | 75 |
76 | 77 | { sidebarItems } 78 | 79 |
80 | ) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /docs/components/home/HomeSidebarItem.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | 7 | var { Tile } = require('react-material-design'); 8 | 9 | 10 | 11 | module.exports = class DocsSidebarItem extends ReactCSS.Component { 12 | 13 | classes() { 14 | return { 15 | 'default': { 16 | sidebarItem: { 17 | fontSize: '14px', 18 | textDecoration: 'none', 19 | color: 'rgba(0, 0, 0, .57)', 20 | transition: 'all 200ms linear' 21 | }, 22 | number: { 23 | fontSize: '14px', 24 | color: 'rgba(0, 0, 0, .27)', 25 | fontWeight: 'bold', 26 | paddingTop: '14px' 27 | }, 28 | li: { 29 | paddingBottom: '8px' 30 | } 31 | }, 32 | 'bold': { 33 | sidebarItem: { 34 | fontWeight: 'bold', 35 | paddingTop: '14px', 36 | display: 'block' 37 | } 38 | }, 39 | 'active': { 40 | sidebarItem: { 41 | color: 'rgba(255,255,255,.87)' 42 | } 43 | } 44 | }; 45 | } 46 | 47 | render() { 48 | return ( 49 |
50 | 51 |
{ this.props.sidebarNumber }
52 | { this.props.label } 53 |
54 |
55 | ) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /docs/components/layout/Container.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | 7 | module.exports = class Container extends ReactCSS.Component { 8 | 9 | classes() { 10 | return { 11 | 'default': { 12 | container: { 13 | maxWidth: '720px', 14 | padding: '0 20px', 15 | margin: '0 auto' 16 | } 17 | } 18 | }; 19 | } 20 | 21 | render(){ 22 | return
{ this.props.children }
23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /docs/components/layout/Grid.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | var context = require('react-context'); 7 | 8 | class Grid extends ReactCSS.Component { 9 | 10 | 11 | 12 | constructor() { 13 | super(); 14 | } 15 | 16 | classes() { 17 | return { 18 | 'default': { 19 | grid: { 20 | position: 'relative' 21 | }, 22 | left: { 23 | position: 'absolute', 24 | width: '130px' 25 | }, 26 | main: { 27 | paddingLeft: '150px' 28 | } 29 | }, 30 | 'no-sidebar': { 31 | left: { 32 | display: 'none' 33 | }, 34 | main: { 35 | paddingLeft: '0' 36 | } 37 | } 38 | }; 39 | } 40 | 41 | styles() { 42 | return this.css({ 43 | 'no-sidebar': this.context.width < 500 44 | }); 45 | } 46 | 47 | render(){ 48 | return ( 49 |
50 |
{ this.props.children[0] }
51 |
{ this.props.children[1] }
52 |
53 | ) 54 | } 55 | }; 56 | 57 | Grid.contextTypes = context.subscribe(['width']); 58 | 59 | module.exports = Grid; 60 | -------------------------------------------------------------------------------- /docs/components/layout/Root.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var context = require('react-context'); 6 | 7 | var Home = require('../home/Home'); 8 | 9 | 10 | 11 | class Root extends React.Component { 12 | 13 | render(){ 14 | return 15 | } 16 | } 17 | 18 | module.exports = context(Root); 19 | -------------------------------------------------------------------------------- /docs/documentation/01-about.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: about 3 | title: About 4 | --- 5 | React context passes down helpful properties for use in your app: 6 | 7 | **Engagement Properties** - AdBlock and Focus 8 | 9 | **Display Properties** - Density, Scroll, Width and Height 10 | 11 | **Device Properties** - Language, OS, Browser and Browser Version 12 | -------------------------------------------------------------------------------- /docs/documentation/02-usage.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: usage 3 | title: Usage 4 | --- 5 | ``` 6 | npm install react-context 7 | ``` 8 | -------------------------------------------------------------------------------- /docs/documentation/02.01-root.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: usage-root 3 | title: Wrap Root 4 | --- 5 | Require `react-context` into your top-most component and wrap the export with the context function. It sets up the context to pass down data to all of your children components. 6 | ``` 7 | var React = require('react'); 8 | var context = require('react-context'); 9 | 10 | var Root = React.createClass({ 11 | render(){ 12 | return
Root
13 | } 14 | }); 15 | 16 | module.exports = context(Root); 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/documentation/02.02-set-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: usage-set-types 3 | title: Set Types 4 | --- 5 | Any child below your root component can now subscribe to any of the context types by defining `contextTypes`. 6 | 7 | Use the `context.subscribe` function as a shortcut to avoid having to define context types. 8 | 9 | ``` 10 | var React = require('react'); 11 | var context = require('react-context'); 12 | 13 | var Child = React.createClass({ 14 | render(){ 15 | return
{ this.context.focus }
16 | } 17 | }); 18 | 19 | Child.contextTypes = context.subscribe(['focus']); 20 | 21 | module.exports = Child; 22 | ``` 23 | Pass it an array of types you want to subscribe to, or call it with no arguments to subscribe to all of them. 24 | ``` 25 | // Subscribe to scroll and adBlock 26 | Child.contextTypes = context.subscribe(['scroll', 'adBlock']); 27 | 28 | // Subscribe to every context 29 | Child.contextTypes = context.subscribe(); 30 | ``` 31 | Otherwise, you can use `contextTypes` the traditional way and include the types you want to subscribe to: 32 | ```javascript 33 | Child.contextTypes = { 34 | pointer: React.PropTypes.string, 35 | density: React.PropTypes.number, 36 | width: React.PropTypes.number, 37 | height: React.PropTypes.number, 38 | language: React.PropTypes.string, 39 | focus: React.PropTypes.bool, 40 | scroll: React.PropTypes.number, 41 | adBlock: React.PropTypes.bool, 42 | os: React.PropTypes.string, 43 | browser: React.PropTypes.string, 44 | browserVersion: React.PropTypes.string 45 | }; 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/documentation/03-contexts.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts 3 | title: Contexts 4 | --- 5 | -------------------------------------------------------------------------------- /docs/documentation/adBlock.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-adblock 3 | title: AdBlock 4 | --- 5 | ``` 6 | this.context.adBlock // bool 7 | 8 | Component.contextTypes = context.subscribe(['adBlock']) 9 | ``` 10 | Utilizes `sitexw/FuckAdBlock` to detect when there is an ad blocker turned on. Valid on Chrome, Firefox, IE (8+), Safari, Opera. 11 | -------------------------------------------------------------------------------- /docs/documentation/browser.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-browser 3 | title: Browser 4 | --- 5 | ``` 6 | this.context.browser // string 7 | 8 | Component.contextTypes = context.subscribe(['browser']) 9 | ``` 10 | Parses userAgent string and returns the browser name. 11 | -------------------------------------------------------------------------------- /docs/documentation/browserVersion.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-browser-version 3 | title: Browser Version 4 | --- 5 | ``` 6 | this.context.browserVersion // string 7 | 8 | Component.contextTypes = context.subscribe(['browserVersion']) 9 | ``` 10 | Parses userAgent string and returns the browser version number. 11 | -------------------------------------------------------------------------------- /docs/documentation/density.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-density 3 | title: Density 4 | --- 5 | ``` 6 | this.context.density // number 7 | 8 | Component.contextTypes = context.subscribe(['density']) 9 | ``` 10 | 11 | Utilizes `window.devicePixelRatio` to tell you the density of the screen. 12 | -------------------------------------------------------------------------------- /docs/documentation/focus.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-focus 3 | title: Focus 4 | --- 5 | ``` 6 | this.context.focus // bool 7 | 8 | Component.contextTypes = context.subscribe(['focus']) 9 | ``` 10 | Sets event listeners for both focus and blur events to tell you when the window is in focus or not. 11 | -------------------------------------------------------------------------------- /docs/documentation/height.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-height 3 | title: Height 4 | --- 5 | ``` 6 | this.context.height // number 7 | 8 | Component.contextTypes = context.subscribe(['height']) 9 | ``` 10 | Sets a resize listener and returns the height of the viewport. 11 | -------------------------------------------------------------------------------- /docs/documentation/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '01-about': require('./01-about.md'), 3 | '02-usage': require('./02-usage.md'), 4 | '02.01-root': require('./02.01-root.md'), 5 | '02.02-set-types': require('./02.02-set-types.md'), 6 | '03-contexts': require('./03-contexts.md'), 7 | '03.01-adBlock': require('./adBlock.md'), 8 | '03.02-browser': require('./browser.md'), 9 | '03.03-browserVersion': require('./browserVersion.md'), 10 | '03.04-density': require('./density.md'), 11 | '03.05-focus': require('./focus.md'), 12 | '03.06-height': require('./height.md'), 13 | '03.07-language': require('./language.md'), 14 | '03.08-os': require('./os.md'), 15 | // '03.09-pointer': require('./pointer.md'), 16 | '03.10-scroll': require('./scroll.md'), 17 | '03.11-width': require('./width.md') 18 | }; 19 | -------------------------------------------------------------------------------- /docs/documentation/language.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-language 3 | title: Language 4 | --- 5 | ``` 6 | this.context.language // string 7 | 8 | Component.contextTypes = context.subscribe(['language']) 9 | ``` 10 | Returns the browser language set for use with i18n. 11 | -------------------------------------------------------------------------------- /docs/documentation/os.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-os 3 | title: OS 4 | --- 5 | ``` 6 | this.context.os // string 7 | 8 | Component.contextTypes = context.subscribe(['os']) 9 | ``` 10 | Parses the userAgent string and returns the OS name. 11 | -------------------------------------------------------------------------------- /docs/documentation/pointer.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-pointer 3 | title: Pointer 4 | --- 5 | ``` 6 | this.context.pointer // string 7 | 8 | Component.contextTypes = context.subscribe(['pointer']) 9 | ``` 10 | -------------------------------------------------------------------------------- /docs/documentation/scroll.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-scroll 3 | title: Scroll 4 | --- 5 | ``` 6 | this.context.scroll // number 7 | 8 | Component.contextTypes = context.subscribe(['scroll']) 9 | ``` 10 | Sets up an event handler for scrolling and returns the amount of pixels scrolled from the top of the page. 11 | -------------------------------------------------------------------------------- /docs/documentation/width.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: contexts-width 3 | title: Width 4 | --- 5 | ``` 6 | this.context.width // number 7 | 8 | Component.contextTypes = context.subscribe(['width']) 9 | ``` 10 | Sets a resize listener and returns the width of the viewport. 11 | -------------------------------------------------------------------------------- /docs/helpers/markdown.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var Remarkable = require('remarkable'); 5 | var hljs = require('highlight.js'); 6 | var regularMd = new Remarkable(); 7 | var codeMd = new Remarkable({ 8 | highlight: function(str) { 9 | try { 10 | return hljs.highlight('javascript', str).value; 11 | // return hljs.highlightAuto(str).value 12 | } 13 | catch(err) { 14 | console.log(err); 15 | } 16 | } 17 | }); 18 | 19 | 20 | module.exports = { 21 | 22 | render: function(text) { 23 | return regularMd.render(text); 24 | }, 25 | 26 | renderCode: function(text) { 27 | return codeMd.render(text); 28 | }, 29 | 30 | getArgs: function(code) { 31 | var args = {}; 32 | if (code.indexOf('---') > -1) { 33 | var match = /---([\s\S]*?)---\n([\s\S]*)/.exec(code); 34 | var argSplit = match[1].trim().split('\n'); 35 | 36 | for (var i = 0; i < argSplit.length; i++) { 37 | var arg = argSplit[i]; 38 | var regex = /(.+?): (.+)/.exec(arg); 39 | args[regex[1]] = regex[2]; 40 | } 41 | code = match[2]; 42 | } 43 | return args; 44 | }, 45 | 46 | getBody: function(code) { 47 | if (code.indexOf('---') > -1) { 48 | var match = /---([\s\S]*?)---\n([\s\S]*)/.exec(code); 49 | return match[2]; 50 | } else { 51 | return code; 52 | } 53 | }, 54 | 55 | isCode: function(text) { 56 | var array = []; 57 | var reg = new RegExp(/(```.*\n([\s\S]*?)```)/g); 58 | var match; 59 | while ((match = reg.exec(text)) !== null) { 60 | array.push( match ); 61 | } 62 | return array; 63 | }, 64 | 65 | isCodeBlock: function(string) { 66 | if (string.indexOf('|Code:') > -1) { 67 | return true; 68 | } else { 69 | return false; 70 | } 71 | }, 72 | 73 | isSubSection: function(string) { 74 | if (string.split('-')[0].indexOf('.') === -1) { 75 | return true ; 76 | } else { 77 | return false; 78 | } 79 | }, 80 | 81 | codeNumber: function(string) { 82 | return /\|Code:(.+?)\|/.exec(string)[1]; 83 | } 84 | 85 | }; 86 | -------------------------------------------------------------------------------- /docs/images/react-context-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/casesandberg/react-context/4038dc571e93a868e90ad4560ec869669a5d33cd/docs/images/react-context-bg.jpg -------------------------------------------------------------------------------- /docs/images/react-context-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/casesandberg/react-context/4038dc571e93a868e90ad4560ec869669a5d33cd/docs/images/react-context-logo.png -------------------------------------------------------------------------------- /docs/index.js: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | require('../node_modules/normalize.css/normalize.css'); 6 | 7 | var Root = require('./components/layout/Root'); 8 | 9 | 10 | React.render( 11 | React.createElement(Root), 12 | document.getElementById('root') 13 | ); 14 | -------------------------------------------------------------------------------- /examples/Child.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var context = require('react-context'); 6 | 7 | 8 | 9 | var Child = React.createClass({ 10 | 11 | // subscribe to all the contextTypes 12 | contextTypes: context.subscribe(), 13 | 14 | render(){ 15 | var contexts = []; 16 | for (var key in this.context){ 17 | var value = this.context[key]; 18 | contexts.push(
{ key }: { value.toString() }
); 19 | } 20 | return( 21 |
{ contexts }
22 | ) 23 | } 24 | }); 25 | 26 | 27 | module.exports = Child; 28 | -------------------------------------------------------------------------------- /examples/Root.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var context = require('react-context'); 6 | 7 | var Child = require('./Child'); 8 | 9 | 10 | var Root = React.createClass({ 11 | 12 | render(){ 13 | return 14 | } 15 | }); 16 | 17 | // Wrap your top-most export 18 | module.exports = context(Root); 19 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/casesandberg/react-context/4038dc571e93a868e90ad4560ec869669a5d33cd/favicon.ico -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | var path = require('path'); 4 | var webpack = require('webpack'); 5 | var WebpackDevServer = require('webpack-dev-server'); 6 | 7 | 8 | 9 | config = { 10 | docs: { 11 | entry: ['webpack-dev-server/client?http://localhost:9100', 'webpack/hot/dev-server', './docs/index.js'], 12 | output: { 13 | path: path.join(__dirname, 'build'), 14 | filename: 'bundle.js', 15 | publicPath: 'http://localhost:9100/build/' 16 | }, 17 | module: { 18 | loaders: [ 19 | { 20 | exclude: /node_modules/, 21 | test: /\.js$/, 22 | loaders: ['react-hot-loader', 'babel-loader'] 23 | }, { 24 | test: /\.jsx$/, 25 | exclude: /node_modules/, 26 | loaders: ['react-hot-loader', 'jsx-loader', 'babel-loader', 'react-map-styles'] 27 | }, { 28 | test: /\.css$/, 29 | loaders: [ 'style-loader', 'css-loader' ] 30 | }, { 31 | test: /\.md$/, 32 | loaders: [ 'html-loader' ] 33 | } 34 | ] 35 | }, 36 | resolve: { 37 | alias: { 38 | 'react-context': path.resolve(__dirname, './src/context'), 39 | 'react': path.resolve(__dirname, './node_modules/react') 40 | }, 41 | extensions: ['', '.js', '.jsx'], 42 | fallback: [ path.resolve(__dirname, './modules') ] 43 | }, 44 | plugins: [ 45 | new webpack.HotModuleReplacementPlugin({ quiet: true }), 46 | new webpack.NoErrorsPlugin() 47 | ], 48 | devtool: 'eval', 49 | quiet: true 50 | } 51 | }; 52 | 53 | gulp.task('docs', function(done) { 54 | done(); 55 | return new WebpackDevServer(webpack(config.docs), { 56 | publicPath: config.docs.output.publicPath, 57 | hot: true, 58 | stats: { 59 | cached: false, 60 | cachedAssets: false, 61 | exclude: ['node_modules', 'components'] 62 | } 63 | }).listen(9100, 'localhost', function(err, result) { 64 | if (err) { 65 | return console.log(err); 66 | } else { 67 | return console.log('webpack dev server listening at localhost:9100'); 68 | } 69 | }); 70 | }); 71 | 72 | 73 | gulp.task('static', function(done){ 74 | 75 | prodConfig = { 76 | entry: ['./docs/index.js'], 77 | output: { 78 | path: path.join(__dirname, '/build'), 79 | filename: 'bundle.js', 80 | publicPath: '/build/' 81 | }, 82 | module: { 83 | loaders: [{ 84 | exclude: /node_modules/, 85 | test: /\.js$/, 86 | loaders: ['babel-loader'] 87 | }, { 88 | test: /\.jsx$/, 89 | exclude: /node_modules/, 90 | loaders: ['jsx-loader', 'babel-loader', 'react-map-styles'] 91 | }, { 92 | test: /\.css$/, 93 | loaders: [ 'style-loader', 'css-loader' ] 94 | }, { 95 | test: /\.md$/, 96 | loaders: [ 'html-loader' ] 97 | } 98 | ] 99 | }, 100 | resolve: { 101 | alias: { 102 | 'react-context': path.resolve(__dirname, './src/context'), 103 | 'react': path.resolve(__dirname, './node_modules/react') 104 | }, 105 | extensions: ['', '.js', '.coffee', '.jsx', '.cjsx'], 106 | fallback: [path.resolve(__dirname, './modules')] 107 | }, 108 | plugins: [ 109 | new webpack.DefinePlugin({ 110 | 'process.env': { 111 | NODE_ENV: JSON.stringify('production') 112 | } 113 | }), 114 | new webpack.optimize.DedupePlugin(), 115 | // new webpack.optimize.UglifyJsPlugin({ 116 | // mangle: { 117 | // except: ['exports', 'require'] 118 | // }, 119 | // sourceMap: false, 120 | // output: {comments: false} 121 | // }), 122 | // new webpack.optimize.CommonsChunkPlugin("common.js") 123 | ], 124 | devtool: 'eval', 125 | quiet: true 126 | }; 127 | 128 | webpack(prodConfig, function(err, stats){ 129 | 130 | if(err) { 131 | throw new Error(err); 132 | } 133 | 134 | done(); 135 | }); 136 | }); 137 | 138 | 139 | gulp.task('default', ['docs']); 140 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | React Context 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 27 | 28 | -------------------------------------------------------------------------------- /modules/react-material-design/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Raised: require('./src/components/Raised'), 3 | Tile: require('./src/components/Tile') 4 | }; 5 | -------------------------------------------------------------------------------- /modules/react-material-design/src/components/Raised.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | 7 | 8 | class Raised extends ReactCSS.Component { 9 | 10 | classes() { 11 | return { 12 | 'default': { 13 | wrap: { 14 | position: 'relative' 15 | }, 16 | content: { 17 | position: 'relative' 18 | }, 19 | bg: { 20 | Absolute: '0 0 0 0', 21 | boxShadow: '0 ${ this.props.zDepth }px ${ this.props.zDepth * 4 }px rgba(0,0,0,.24)', 22 | borderRadius: this.props.radius, 23 | background: this.props.background 24 | } 25 | }, 26 | 'zDepth-0': { 27 | bg: { 28 | boxShadow: 'none' 29 | } 30 | }, 31 | 32 | 'zDepth-1': { 33 | bg: { 34 | boxShadow: '0 2px 10px rgba(0,0,0,.12), 0 2px 5px rgba(0,0,0,.16)' 35 | } 36 | }, 37 | 'zDepth-2': { 38 | bg: { 39 | boxShadow: '0 6px 20px rgba(0,0,0,.19), 0 8px 17px rgba(0,0,0,.2)' 40 | } 41 | }, 42 | 'zDepth-3': { 43 | bg: { 44 | boxShadow: '0 17px 50px rgba(0,0,0,.19), 0 12px 15px rgba(0,0,0,.24)' 45 | } 46 | }, 47 | 'zDepth-4': { 48 | bg: { 49 | boxShadow: '0 25px 55px rgba(0,0,0,.21), 0 16px 28px rgba(0,0,0,.22)' 50 | } 51 | }, 52 | 'zDepth-5': { 53 | bg: { 54 | boxShadow: '0 40px 77px rgba(0,0,0,.22), 0 27px 24px rgba(0,0,0,.2)' 55 | } 56 | }, 57 | 'square': { 58 | bg: { 59 | borderRadius: '0' 60 | } 61 | }, 62 | 'circle': { 63 | bg: { 64 | borderRadius: '50%' 65 | } 66 | } 67 | }; 68 | } 69 | 70 | render() { 71 | return ( 72 |
73 |
74 |
{ this.props.children }
75 |
76 | ) 77 | } 78 | } 79 | 80 | Raised.propTypes = { 81 | background: React.PropTypes.string, 82 | zDepth: React.PropTypes.oneOf(['0', '1', '2', '3', '4', '5', 0, 1, 2, 3, 4, 5]), 83 | radius: React.PropTypes.oneOfType([ 84 | React.PropTypes.string, 85 | React.PropTypes.number 86 | ]) 87 | } 88 | 89 | Raised.defaultProps = { 90 | background: '#fff', 91 | zDepth: '1', 92 | radius: '2px' 93 | } 94 | 95 | module.exports = Raised 96 | -------------------------------------------------------------------------------- /modules/react-material-design/src/components/Tile.jsx: -------------------------------------------------------------------------------- 1 | /* jshint node: true, esnext: true */ 2 | "use strict"; 3 | 4 | var React = require('react'); 5 | var ReactCSS = require('reactcss'); 6 | 7 | 8 | 9 | module.exports = class Tile extends ReactCSS.Component { 10 | 11 | classes() { 12 | return { 13 | 'default': { 14 | tile: { 15 | fontSize: '16px', 16 | padding: '16px', 17 | display: 'flex', 18 | justifyContent: 'space-between', 19 | color: this.props.color 20 | }, 21 | primary: { 22 | display: 'flex', 23 | width: '100%' 24 | }, 25 | sidebar: { 26 | minWidth: '56px', 27 | maxWidth: '56px', 28 | flexBasis: '56' // 72 minus 16 29 | }, 30 | content: { 31 | background: 'none', 32 | flex: '1', 33 | maxWidth: '95%' 34 | }, 35 | secondary: { 36 | flexBasis: '42', 37 | textAlign: 'center' 38 | }, 39 | sidebarIcon: { 40 | marginTop: '-12px', 41 | marginLeft: '-12px', 42 | marginBottom: '-12px' 43 | }, 44 | }, 45 | 'divider': { 46 | tile: { 47 | boxShadow: 'inset 0 -1px 0 rgba(0,0,0,.12)' 48 | }, 49 | }, 50 | 'condensed': { 51 | tile: { 52 | paddingBottom: '0', 53 | paddingTop: '0' 54 | }, 55 | sidebar: { 56 | minWidth: '28px', 57 | maxWidth: '28px', 58 | flexBasis: '28' 59 | } 60 | } 61 | }; 62 | } 63 | 64 | styles() { 65 | return this.css({ 66 | 'clickable': this.props.onClick 67 | }); 68 | } 69 | 70 | render() { 71 | var [ sidebar, content ] = this.props.children; 72 | 73 | return ( 74 |
75 | 76 |
77 |
78 | { sidebar } 79 |
80 |
81 | { content } 82 |
83 |
84 |
85 | ) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-context", 3 | "version": "0.0.3", 4 | "description": "Helpful Properties with React Context", 5 | "main": "src/context", 6 | "dependencies": { 7 | "react": "^0.14.7", 8 | "reactcss": "^0.4.5" 9 | }, 10 | "devDependencies": { 11 | "babel-loader": "^6.2.4", 12 | "css-loader": "^0.23.1", 13 | "gulp": "^3.9.0", 14 | "highlight.js": "^9.2.0", 15 | "html-loader": "^0.4.3", 16 | "jsx-loader": "^0.13.2", 17 | "node-libs-browser": "^1.0.0", 18 | "normalize.css": "^3.0.3", 19 | "react-hot-loader": "^1.2.7", 20 | "react-map-styles": "^0.3.0", 21 | "remarkable": "^1.6.0", 22 | "style-loader": "^0.13.0", 23 | "webpack": "^1.10.1", 24 | "webpack-dev-server": "^1.10.1" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/casesandberg/react-context.git" 29 | }, 30 | "keywords": [ 31 | "react", 32 | "context", 33 | "react-context" 34 | ], 35 | "author": "case ", 36 | "license": "MIT", 37 | "bugs": { 38 | "url": "https://github.com/casesandberg/react-context/issues" 39 | }, 40 | "homepage": "http://casesandberg.github.io/react-context/" 41 | } 42 | -------------------------------------------------------------------------------- /src/context.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var React = require('react') 4 | 5 | var contextTypes = { 6 | pointer: React.PropTypes.string, 7 | density: React.PropTypes.number, 8 | width: React.PropTypes.number, 9 | height: React.PropTypes.number, 10 | language: React.PropTypes.string, 11 | focus: React.PropTypes.bool, 12 | scroll: React.PropTypes.number, 13 | adBlock: React.PropTypes.bool, 14 | os: React.PropTypes.string, 15 | browser: React.PropTypes.string, 16 | browserVersion: React.PropTypes.string, 17 | } 18 | 19 | var context = function(Component) { 20 | 21 | var Context = React.createClass({ 22 | 23 | getInitialState: function() { 24 | return { 25 | width: window.innerWidth, 26 | height: window.innerHeight, 27 | focus: document.hasFocus(), 28 | scroll: window.scrollY, 29 | adBlock: false, 30 | } 31 | }, 32 | 33 | childContextTypes: contextTypes, 34 | 35 | getChildContext: function() { 36 | return { 37 | // pointer: (('ontouchstart' in window) || (window.DocumentTouch && document instanceof DocumentTouch) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) ? 'touch' : 'mouse', 38 | density: window.devicePixelRatio, 39 | width: this.state.width, 40 | height: this.state.height, 41 | language: window.navigator.userLanguage || window.navigator.language, 42 | focus: this.state.focus, 43 | scroll: this.state.scroll, 44 | adBlock: this.state.adBlock, 45 | os: this.checkOS(), 46 | browser: this.checkBrowser().browser, 47 | browserVersion: this.checkBrowser().version, 48 | } 49 | }, 50 | 51 | // (C) viazenetti GmbH (Christian Ludwig) 52 | // http://jsfiddle.net/ChristianL/AVyND/ 53 | checkOS: function() { 54 | var os 55 | var clientStrings = [ 56 | { 57 | s:'Windows', 58 | r:/(Windows)/, 59 | }, { 60 | s:'Android', 61 | r:/Android/, 62 | }, { 63 | s:'Open BSD', 64 | r:/OpenBSD/, 65 | }, { 66 | s:'Linux', 67 | r:/(Linux|X11)/, 68 | }, { 69 | s:'iOS', 70 | r:/(iPhone|iPad|iPod)/, 71 | }, { 72 | s:'Mac', 73 | r:/Mac/, 74 | }, { 75 | s:'UNIX', 76 | r:/UNIX/, 77 | }, { 78 | s:'Robot', 79 | r:/(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/, 80 | }, 81 | ] 82 | 83 | for (var i = 0; i < clientStrings.length; i++) { 84 | var cs = clientStrings[i] 85 | if (cs.r.test(navigator.userAgent)) { 86 | return cs.s 87 | } 88 | } 89 | }, 90 | 91 | // (C) viazenetti GmbH (Christian Ludwig) 92 | // http://jsfiddle.net/ChristianL/AVyND/ 93 | checkBrowser: function() { 94 | var UA = navigator.userAgent 95 | var browser 96 | var version 97 | var verOffset 98 | var nameOffset 99 | 100 | if ((verOffset = UA.indexOf('Opera')) > -1) { 101 | browser = 'Opera' 102 | version = UA.substring(verOffset + 6) 103 | if ((verOffset = UA.indexOf('Version')) > -1) { 104 | version = UA.substring(verOffset + 8) 105 | } 106 | } else if ((verOffset = UA.indexOf('MSIE')) > -1) { 107 | browser = 'Internet Explorer' 108 | version = UA.substring(verOffset + 5) 109 | } else if ((verOffset = UA.indexOf('Chrome')) > -1) { 110 | browser = 'Chrome' 111 | version = UA.substring(verOffset + 7) 112 | } else if ((verOffset = UA.indexOf('Safari')) > -1) { 113 | browser = 'Safari' 114 | version = UA.substring(verOffset + 7) 115 | if ((verOffset = UA.indexOf('Version')) > -1) { 116 | version = UA.substring(verOffset + 8) 117 | } 118 | } else if ((verOffset = UA.indexOf('Firefox')) > -1) { 119 | browser = 'Firefox' 120 | version = UA.substring(verOffset + 8) 121 | } else if (UA.indexOf('Trident/') > -1) { 122 | browser = 'Internet Explorer' 123 | version = UA.substring(UA.indexOf('rv:') + 3) 124 | } else if ((nameOffset = UA.lastIndexOf(' ') + 1) < (verOffset = UA.lastIndexOf('/'))) { 125 | browser = UA.substring(nameOffset, verOffset) 126 | version = UA.substring(verOffset + 1) 127 | if (browser.toLowerCase() == browser.toUpperCase()) { 128 | browser = navigator.appName 129 | } 130 | } 131 | 132 | return { 133 | browser: browser, 134 | version: version, 135 | } 136 | }, 137 | 138 | componentDidMount: function() { 139 | window.addEventListener('resize', this.handleResize, false) 140 | window.addEventListener('focus', this.handleFocus, false) 141 | window.addEventListener('blur', this.handleFocus, false) 142 | window.addEventListener('scroll', this.handleScroll, false) 143 | this.checkForAdBlock() 144 | }, 145 | 146 | componentWillUnmount: function() { 147 | window.removeEventListener('resize', this.handleResize, false) 148 | window.removeEventListener('focus', this.handleFocus, false) 149 | window.removeEventListener('blur', this.handleFocus, false) 150 | window.removeEventListener('scroll', this.handleScroll, false) 151 | }, 152 | 153 | handleScroll: function() { 154 | this.setState({ 155 | scroll: window.scrollY, 156 | }) 157 | }, 158 | 159 | // Cross-browser height and width values 160 | // http://stackoverflow.com/a/8876069/989006 161 | handleResize: function() { 162 | this.setState({ 163 | width: Math.max(document.documentElement.clientWidth, window.innerWidth || 0), 164 | height: Math.max(document.documentElement.clientHeight, window.innerHeight || 0), 165 | }) 166 | }, 167 | 168 | handleFocus: function(e) { 169 | this.setState({ 170 | focus: e.type === 'focus' ? true : false, 171 | }) 172 | }, 173 | 174 | // FuckAdBlock 3.1.1 175 | // Copyright (c) 2015 Valentin Allaire 176 | // Released under the MIT license 177 | // https://github.com/sitexw/FuckAdBlock 178 | checkForAdBlock: function() { 179 | var ad = React.findDOMNode(this.refs.fakeAd) 180 | 181 | if (ad) { 182 | if (window.document.body.getAttribute('abp') !== null || 183 | ad.offsetParent === null || ad.offsetHeight === 0 || 184 | ad.offsetLeft === 0 || ad.offsetTop === 0 || 185 | ad.offsetWidth === 0 || ad.clientHeight === 0 || 186 | ad.clientWidth === 0) { 187 | this.setState({ adBlock: true }) 188 | } 189 | 190 | if (window.getComputedStyle !== undefined) { 191 | var adStyles = window.getComputedStyle(ad, null) 192 | 193 | if (adStyles.getPropertyValue('display') == 'none' || 194 | adStyles.getPropertyValue('visibility') == 'hidden') { 195 | this.setState({ adBlock: true }) 196 | } 197 | } 198 | } 199 | }, 200 | 201 | render: function() { 202 | var fakeAdClasses = 'pub_300x250 pub_300x250m pub_728x90 text-ad textAd text_ad text_ads text-ads text-ad-links' 203 | var fakeAdStyles = { 204 | width: '1px !important', 205 | height: '1px !important', 206 | position: 'absolute !important', 207 | left: '-10000px !important', 208 | top: '-1000px !important', 209 | } 210 | 211 | return React.createElement('div', null, 212 | React.createElement('div', { ref: "fakeAd", className: fakeAdClasses, style: fakeAdStyles }), 213 | React.createElement(Component, this.props) 214 | ) 215 | }, 216 | }) 217 | 218 | return Context 219 | } 220 | 221 | context.subscribe = function(lookup) { 222 | if (!lookup) { 223 | return contextTypes 224 | } else { 225 | var customTypes = {} 226 | for (var i = 0; i < lookup.length; i++) { 227 | var type = lookup[i] 228 | if (contextTypes[type]) { 229 | customTypes[type] = contextTypes[type] 230 | } else { 231 | console.warn('Context type `' + type + '` does not exist') 232 | } 233 | } 234 | 235 | return customTypes 236 | } 237 | } 238 | 239 | module.exports = context 240 | --------------------------------------------------------------------------------