├── .gitignore
├── .npmignore
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── examples
├── ChildSpans.cjsx
├── ComplexResponsiveLayout.cjsx
├── Controls.cjsx
├── Intro.cjsx
├── PrePostSquish.cjsx
├── Router.cjsx
├── ThreeColumn.cjsx
├── TwoColumn.cjsx
├── index.cjsx
└── index.html
├── package.json
├── src
├── components
│ ├── Breakpoint.cjsx
│ ├── Container.cjsx
│ ├── Grid.cjsx
│ └── Span.cjsx
├── index.cjsx
└── utils
│ └── SpanCalculate.coffee
├── test
└── calc.coffee
├── webpack.config.js
└── webpack.config.production.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 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Commenting this out is preferred by some people, see
24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
25 | node_modules
26 |
27 | # Users Environment Variables
28 | .lock-wscript
29 | susy-test/
30 | examples/bundle.js
31 | dist/
32 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
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 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Commenting this out is preferred by some people, see
24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
25 | node_modules
26 |
27 | # Users Environment Variables
28 | .lock-wscript
29 | susy-test/
30 | examples/bundle.js
31 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js:
4 | - "0.10"
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Kyle Mathews
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 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BIN = ./node_modules/.bin
2 |
3 | release-patch:
4 | @$(call release,patch)
5 |
6 | release-minor:
7 | @$(call release,minor)
8 |
9 | release-major:
10 | @$(call release,major)
11 |
12 | build:
13 | @$(BIN)/cjsx -cb -o dist/ src/
14 | @$(BIN)/webpack
15 |
16 | watch:
17 | @$(BIN)/webpack-dev-server -w
18 |
19 | publish:
20 | git push --tags origin HEAD:master
21 | @$(BIN)/cjsx -cb -o dist/ src/
22 | npm publish
23 |
24 | publish-gh-pages:
25 | git checkout gh-pages
26 | git merge master
27 | @$(BIN)/webpack --config webpack.config.production.js
28 | cp examples/* .
29 | git add --all .
30 | git commit -m "New release"
31 | git push origin gh-pages
32 | git checkout master
33 |
34 | define release
35 | npm version $(1)
36 | endef
37 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](http://travis-ci.org/KyleAMathews/react-responsive-grid)
3 |
4 | # react-responsive-grid
5 | Power tools for building responsive layouts with React.
6 |
7 | WIP, porting best ideas from [Susy](http://susy.oddbird.net/) to a React-friendly and CSS-independent format.
8 |
9 | ### Susy porting progress
10 | #### Container
11 | - [x] Basic fluid container
12 | - [ ] static
13 | - [ ] non-centered layouts
14 | - [ ] container positions (left, center (default), right, length (left
15 | and right))
16 |
17 | #### Breakpoint
18 | - [x] Basic component width breakpoints (note this is different than a
19 | media query breakpoint)
20 | - [ ] Media query breakpoints
21 |
22 | #### Columns
23 | - [x] set number of columns
24 | - [ ] list — create asymmetrical grids. List the size of each column
25 | relative to other columns where 1 is a single column-unit. (1,2) would
26 | create a 2-column grid where the second column being twice the width of
27 | the first.
28 |
29 | #### Gutter options
30 | - [x] margin-based
31 | - [ ] padding-based
32 | - [ ] explicit gutter width
33 |
34 | #### Gutter positions
35 | - [ ] before
36 | - [x] after
37 | - [ ] inside
38 | - [ ] inside-static
39 | - [ ] split
40 |
41 | #### Span
42 | - [x] Set # of columns
43 | - [ ] Set arbitrary width
44 | - [x] Remove last gutter by "last" prop
45 | - [ ] Remove first gutter by "first" prop
46 | - [x] Support nested spans
47 | - [x] Set location of span using "at" prop
48 | - [ ] Span external gutters (in addition to internal gutters)
49 | - [x] "break" prop — start new row by clearing previous spans
50 | - [ ] No gutters option
51 | - [ ] "full" prop — shortcut for a span to fill its entire context
52 | - [x] "pre" prop — add margin before a span
53 | - [x] "post" prop — add margin after a span
54 | - [x] "squish" prop — shortcut for adding pre and post margins to the
55 | same span
56 | - [ ] "pull" prop — add negative margin before a span pulling it against
57 | the direction of flow
58 | - [ ] "prefix" prop — add padding before a span
59 | - [ ] "suffix" prop — add padding after a span
60 | - [ ] "pad" prop — add padding before and after a span
61 | - [ ] "bleed" prop — Apply negative margins and equal positive padding
62 | so that span borders and backgrounds "bleed" outside of their
63 | containers
64 | - [ ] "bleed-x" prop — a shortcut for applying only left and right
65 | (horixontal) bleed
66 | - [ ] "bleed-y" prop — a shortcut for applying only top and bottom
67 | (vertical) bleed
68 |
69 | #### Debuggin
70 | - [ ] Show grid
71 |
--------------------------------------------------------------------------------
/examples/ChildSpans.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | {Container, Grid, Breakpoint, Span} = require '../src/index'
3 |
4 | module.exports = React.createClass
5 | render: ->
6 |
7 |
Child spans
8 |
9 | Code
10 |
11 |
12 |
13 | Hi
14 |
15 |
16 |
17 |
18 | I'm a child span with 1 column
19 |
20 |
21 |
22 |
23 | I'm a child span with 3 columns
24 |
25 |
26 |
27 |
28 | I'm a child span with 4 columns
29 |
30 |
31 |
32 |
33 | I'm a child span with 3 columns
34 |
35 |
36 |
37 |
38 | I'm a child span with 1 column
39 |
40 |
41 |
42 |
43 | Hi
44 |
45 |
46 | Hi
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/examples/ComplexResponsiveLayout.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | {Container, Grid, Breakpoint, Span} = require '../src/index'
3 |
4 | purpleStyle =
5 | border: '2px solid purple'
6 | color: 'purple'
7 | height: '10rem'
8 | fontSize: '2rem'
9 | lineHeight: '10rem'
10 | marginBottom: '1rem'
11 | textAlign: 'center'
12 |
13 | module.exports = React.createClass
14 | render: ->
15 |
16 |
More complex layout taken from http://www.zell-weekeat.com/smarter-layouts-with-susy/
17 |
Shrink screen to see simplified layout for small devices
18 |
19 | Code
20 |
21 |
22 |
23 |
24 | 1
25 |
26 |
27 | 2
28 |
29 |
30 |
31 | 3
32 |
33 |
34 | 4
35 |
36 |
37 | 5
38 |
39 |
40 |
41 | 6
42 |
43 |
44 | 7
45 |
46 |
47 |
48 | 8
49 |
50 |
51 | 9
52 |
53 |
54 | 10
55 |
56 |
57 |
58 |
59 |
60 | 1
61 |
62 |
63 |
64 | 2
65 |
66 |
67 | 3
68 |
69 |
70 |
71 | 4
72 |
73 |
74 | 5
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/examples/Controls.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | {Link} = require 'react-router'
3 |
4 | module.exports = React.createClass
5 | render: ->
6 |
7 | - Introduction
8 | - Two-column layout
9 | - Three-column layout
10 | - Child spans
11 | - Complex responsive layout
12 | - pre, post, squish
13 |
14 |
--------------------------------------------------------------------------------
/examples/Intro.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 |
3 | module.exports = React.createClass
4 | render: ->
5 |
6 |
React Responsive Grid
7 |
This is a long introductionary paragraph
8 |
9 |
10 |
--------------------------------------------------------------------------------
/examples/PrePostSquish.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | {Container, Grid, Breakpoint, Span} = require '../src/index'
3 |
4 | purpleStyle =
5 | border: '2px solid purple'
6 | color: 'purple'
7 | height: '10rem'
8 | fontSize: '1rem'
9 | lineHeight: '10rem'
10 | marginBottom: '1rem'
11 | textAlign: 'center'
12 |
13 | module.exports = React.createClass
14 | render: ->
15 |
16 |
Demo squish, post, pre
17 |
18 | Code
19 |
20 |
Squish
21 |
22 | {""}
23 | {""}
24 | {""}
25 | {""}
26 | {""}
27 |
28 |
Pre
29 |
30 | {""}
31 | {""}
32 | {""}
33 | {""}
34 | {""}
35 |
36 |
Post
37 |
38 | {""}
39 | {""}
40 | {""}
41 | {""}
42 | {""}
43 |
44 |
Using them together
45 |
46 | {""}
47 | {""}
48 | {""}
49 | {"
50 | {"
51 | {"
52 | {"
53 | {""}
54 | {""}
55 | {""}
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/examples/Router.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | {render} = require 'react-dom'
3 | {browserHistory, Router, Route, IndexRoute} = require 'react-router'
4 | {Container, Grid, Breakpoint, Span} = require '../src/index'
5 |
6 | Typography = require 'typography'
7 | typography = Typography()
8 | {injectStyles, rhythm} = typography
9 | injectStyles()
10 |
11 | Controls = require './Controls'
12 | Intro = require './Intro'
13 |
14 | App = React.createClass
15 | render: ->
16 |
17 |
26 |
27 |
28 |
33 | {@props.children}
34 |
35 |
36 |
37 | routes = (
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | )
47 |
48 | render(, document.getElementById("mount-point"))
49 |
--------------------------------------------------------------------------------
/examples/ThreeColumn.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | faker = require 'faker'
3 | {Container, Grid, Breakpoint, Span} = require '../src/index'
4 |
5 | module.exports = React.createClass
6 | render: ->
7 |
8 |
Simple three column layout
9 |
10 | Code
11 |
12 |
13 |
14 | Left column
19 |
20 |
21 | {faker.lorem.paragraphs(6)}
26 |
27 |
28 | Right column
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/examples/TwoColumn.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | faker = require 'faker'
3 | {Container, Grid, Breakpoint, Span} = require '../src/index'
4 |
5 | module.exports = React.createClass
6 | render: ->
7 |
8 |
Responsive two column layout
9 |
10 | Code
11 |
12 |
13 |
14 |
15 | {faker.lorem.paragraphs(6)}
20 |
21 |
22 | Right column
27 |
28 |
29 |
30 | Right column
35 | {faker.lorem.paragraphs(6)}
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/examples/index.cjsx:
--------------------------------------------------------------------------------
1 | React = require('react')
2 | Examples = require './examples'
3 |
4 | React.render(, document.body)
5 |
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Example
4 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-responsive-grid",
3 | "description": "Power tools for responsive layouts with React",
4 | "version": "0.3.4",
5 | "author": "Kyle Mathews ",
6 | "bugs": {
7 | "url": "https://github.com/KyleAMathews/react-responsive-grid/issues"
8 | },
9 | "dependencies": {
10 | "object-assign": "^4.0.1",
11 | "react-component-width-mixin": "^2.0.0",
12 | "react-page-width": "^1.0.1"
13 | },
14 | "devDependencies": {
15 | "chai": "^3.4.0",
16 | "cjsx-loader": "^3.0.0",
17 | "coffee-loader": "^0.7.2",
18 | "coffee-react": "^5.0.0",
19 | "coffee-script": "^1.9.2",
20 | "css-loader": "^0.23.1",
21 | "faker": "^3.1.0",
22 | "gulp": "^3.8.11",
23 | "mocha": "^2.2.5",
24 | "mocha-unfunk-reporter": "^0.4.0",
25 | "node-libs-browser": "^1.0.0",
26 | "pre-commit": "^1.0.7",
27 | "react": "^15.0.1",
28 | "react-dom": "^15.0.1",
29 | "react-hot-loader": "^1.2.7",
30 | "react-router": "^2.2.4",
31 | "style-loader": "^0.13.0",
32 | "typography": "^0.7.0",
33 | "underscore": "^1.8.3",
34 | "webpack": "^1.9.7",
35 | "webpack-dev-server": "^1.8.2"
36 | },
37 | "directories": {
38 | "example": "examples"
39 | },
40 | "homepage": "https://github.com/KyleAMathews/react-responsive-grid",
41 | "keywords": [
42 | "960",
43 | "fluid",
44 | "grid",
45 | "layout",
46 | "react",
47 | "react-component",
48 | "responsive",
49 | "rwd",
50 | "semantic",
51 | "susy"
52 | ],
53 | "license": "MIT",
54 | "main": "dist/index.js",
55 | "peerDependencies": {
56 | "react": ">=0.13.0"
57 | },
58 | "repository": {
59 | "type": "git",
60 | "url": "https://github.com/KyleAMathews/react-responsive-grid.git"
61 | },
62 | "scripts": {
63 | "test-watch": "NODE_ENV=test node_modules/.bin/mocha -w --recursive --compilers coffee:coffee-script/register -R mocha-unfunk-reporter",
64 | "test": "NODE_ENV=test node_modules/.bin/mocha --recursive --compilers coffee:coffee-script/register -R mocha-unfunk-reporter"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/components/Breakpoint.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | componentWidthMixin = require 'react-component-width-mixin'
3 | PageWidthMixin = require 'react-page-width'
4 | objectAssign = require 'object-assign'
5 |
6 | ComponentWidthComponent = React.createClass
7 | displayName: "Breakpoint"
8 |
9 | mixins: [componentWidthMixin]
10 |
11 | propTypes:
12 | minWidth: React.PropTypes.number
13 | maxWidth: React.PropTypes.number
14 |
15 | getDefaultProps: ->
16 | {
17 | minWidth: 0
18 | maxWidth: 1000000000000000000000
19 | }
20 |
21 | renderChildren: ->
22 | React.Children.map(@props.children, (child) =>
23 | if child?.type?.displayName is "Span"
24 | React.cloneElement(child, {
25 | context: @props.context
26 | })
27 | else
28 | child
29 | )
30 |
31 | render: ->
32 | props = objectAssign {}, @props
33 | delete props.maxWidth
34 | delete props.minWidth
35 | delete props.widthMethod
36 |
37 | if @state.componentWidth
38 | if @props.minWidth <= @state.componentWidth < @props.maxWidth
39 | {@renderChildren()}
40 | else
41 | return
42 | else
43 | return
44 |
45 | PageWidthComponent = React.createClass
46 | displayName: "Breakpoint"
47 |
48 | mixins: [PageWidthMixin]
49 |
50 | propTypes:
51 | minWidth: React.PropTypes.number
52 | maxWidth: React.PropTypes.number
53 |
54 | getDefaultProps: ->
55 | {
56 | minWidth: 0
57 | maxWidth: 1000000000000000000000
58 | }
59 |
60 | renderChildren: ->
61 | React.Children.map(@props.children, (child) =>
62 | if child.type?.displayName is "Span"
63 | React.cloneElement(child, {
64 | context: @props.context
65 | })
66 | else
67 | child
68 | )
69 |
70 | render: ->
71 | props = objectAssign {}, @props
72 | delete props.maxWidth
73 | delete props.minWidth
74 | delete props.widthMethod
75 |
76 | if @state.pageWidth
77 | if @props.minWidth <= @state.pageWidth < @props.maxWidth
78 | {@renderChildren()}
79 | else
80 | return
81 | else
82 | return
83 |
84 | module.exports = React.createClass
85 | displayName: 'Breakpoint'
86 |
87 | propTypes:
88 | widthMethod: React.PropTypes.string.isRequired
89 | minWidth: React.PropTypes.number
90 | maxWidth: React.PropTypes.number
91 |
92 | getDefaultProps: ->
93 | widthMethod: 'pageWidth'
94 |
95 | render: ->
96 | if @props.widthMethod is "pageWidth"
97 |
98 | else if @props.widthMethod is "componentWidth"
99 |
100 |
--------------------------------------------------------------------------------
/src/components/Container.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | objectAssign = require('object-assign')
3 |
4 | module.exports = React.createClass
5 | displayName: "Container"
6 |
7 | render: ->
8 | defaultStyles =
9 | maxWidth: '960px'
10 | marginLeft: 'auto'
11 | marginRight: 'auto'
12 |
13 | styles = objectAssign defaultStyles, @props.style
14 | children = @props.children
15 |
16 | props = objectAssign {}, @props
17 | delete props.children
18 | delete props.style
19 |
20 |
21 | {children}
22 | {' '}
23 |
24 |
--------------------------------------------------------------------------------
/src/components/Grid.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | objectAssign = require('object-assign')
3 |
4 | module.exports = React.createClass
5 | displayName: "Grid"
6 |
7 | propTypes:
8 | columns: React.PropTypes.number
9 | gutterRatio: React.PropTypes.number
10 |
11 | getDefaultProps: ->
12 | {
13 | columns: 12
14 | gutterRatio: 1/4
15 | }
16 |
17 | renderChildren: ->
18 | React.Children.map(@props.children, (child) =>
19 | if child.type?.displayName in ["Breakpoint", "Span"]
20 | React.cloneElement(child, {
21 | context:
22 | columns: @props.columns
23 | gutterRatio: @props.gutterRatio
24 | })
25 | else
26 | child
27 | )
28 |
29 | render: ->
30 | props = objectAssign {}, @props
31 | delete props.gutterRatio
32 | delete props.columns
33 |
34 |
35 | {@renderChildren()}
36 | {' '}
37 |
38 |
--------------------------------------------------------------------------------
/src/components/Span.cjsx:
--------------------------------------------------------------------------------
1 | React = require 'react'
2 | objectAssign = require('object-assign')
3 |
4 | spanCalculate = require '../utils/SpanCalculate'
5 |
6 | module.exports = React.createClass
7 | displayName: "Span"
8 |
9 | propTypes:
10 | context: React.PropTypes.object
11 | columns: React.PropTypes.number
12 | at: React.PropTypes.number
13 | pre: React.PropTypes.number
14 | post: React.PropTypes.number
15 | squish: React.PropTypes.number
16 | last: React.PropTypes.bool
17 | break: React.PropTypes.bool
18 |
19 | getDefaultProps: ->
20 | at: 0
21 | pre: 0
22 | post: 0
23 | squish: 0
24 | last: false
25 | first: false
26 | break: false
27 |
28 | renderChildren: ->
29 | React.Children.map(@props.children, (child) =>
30 | if child?.type?.displayName is "Span"
31 | React.cloneElement(child, {
32 | # Sub-spans need to know # of columns of parent.
33 | context:
34 | columns: @props.columns
35 | gutterRatio: @props.context.gutterRatio
36 | })
37 | else
38 | child
39 | )
40 |
41 | render: ->
42 | style = spanCalculate({
43 | contextColumns: @props.context.columns
44 | gutterRatio: @props.context.gutterRatio
45 | columns: @props.columns
46 | at: @props.at
47 | pre: @props.pre
48 | post: @props.post
49 | squish: @props.squish
50 | last: @props.last
51 | break: @props.break
52 | })
53 |
54 | style = objectAssign style, @props.style
55 |
56 | props = objectAssign {}, @props, {"style": style}
57 | delete props.at
58 | delete props.break
59 | delete props.columns
60 | delete props.context
61 | delete props.first
62 | delete props.last
63 | delete props.post
64 | delete props.pre
65 | delete props.squish
66 | delete props.style
67 |
68 |
69 | {@renderChildren()}
70 | {' '}
71 |
72 |
--------------------------------------------------------------------------------
/src/index.cjsx:
--------------------------------------------------------------------------------
1 | exports.Container = require './components/Container'
2 | exports.Grid = require './components/Grid'
3 | exports.Breakpoint = require './components/Breakpoint'
4 | exports.Span = require './components/Span'
5 |
--------------------------------------------------------------------------------
/src/utils/SpanCalculate.coffee:
--------------------------------------------------------------------------------
1 | objectAssign = require('object-assign')
2 |
3 | module.exports = (options) ->
4 | defaults =
5 | columns: 3
6 | at: 0
7 | pre: 0
8 | post: 0
9 | squish: 0
10 | contextColumns: 12
11 | gutterRatio: 1/4
12 | first: false
13 | last: false
14 |
15 | ops = objectAssign defaults, options
16 |
17 | # Calculate the width of one column.
18 | n = 100/(ops.contextColumns + ((ops.contextColumns-1) * ops.gutterRatio))
19 |
20 | # Calculate the width of a gutter.
21 | gutterWidth = ops.gutterRatio * n
22 |
23 | # Function to calculate width of a span.
24 | calcSpanWidth = (numColumns) ->
25 | n*numColumns + gutterWidth*(numColumns-1)
26 |
27 | calcSpacing = (numColumns) ->
28 | if numColumns is 0
29 | return 0
30 | else
31 | calcSpanWidth(numColumns) + gutterWidth
32 |
33 | # width
34 | width = calcSpanWidth(ops.columns)
35 |
36 | # marginLeft
37 | if ops.at is 0 and ops.pre is 0 and ops.squish is 0
38 | marginLeft = 0
39 | else
40 | marginLeft =
41 | calcSpacing(ops.at) +
42 | calcSpacing(ops.pre) +
43 | calcSpacing(ops.squish)
44 |
45 | # marginRight
46 | if ops.last and ops.post is 0 and ops.squish is 0
47 | marginRight = 0
48 | else if ops.post isnt 0 or ops.squish isnt 0
49 | marginRight =
50 | calcSpacing(ops.post) +
51 | calcSpacing(ops.squish)
52 |
53 | unless ops.last
54 | marginRight = marginRight + gutterWidth
55 |
56 | else
57 | marginRight = gutterWidth
58 |
59 | # float
60 | if ops.last
61 | float = "right"
62 | else
63 | float = "left"
64 |
65 | # Add %
66 | width = width + "%"
67 | marginLeft = marginLeft + "%"
68 | marginRight = marginRight + "%"
69 |
70 | return {
71 | float: float
72 | marginLeft: marginLeft
73 | marginRight: marginRight
74 | width: width
75 | clear: if ops.break then 'both' else 'none'
76 | }
77 |
--------------------------------------------------------------------------------
/test/calc.coffee:
--------------------------------------------------------------------------------
1 | chai = require 'chai'
2 | expect = chai.expect
3 | _ = require 'underscore'
4 |
5 | spanCalculate = require '../src/utils/SpanCalculate'
6 |
7 | describe 'grid calculate module', ->
8 | it 'should exist', ->
9 | expect(spanCalculate).to.exist
10 |
11 | it 'should return an object', ->
12 | expect(spanCalculate()).to.be.instanceof(Object)
13 |
14 | it 'should return an object that includes style keys', ->
15 | expect(_.keys(spanCalculate())).to.deep.equal([
16 | 'float'
17 | 'marginLeft'
18 | 'marginRight'
19 | 'width'
20 | 'clear'
21 | ])
22 |
23 | it 'should set marginLeft if at isn\'t 0', ->
24 | styles = spanCalculate({at: 1, columns: 3})
25 | noAtstyles = spanCalculate({at: 0, columns: 3})
26 |
27 | expect(styles.marginLeft).to.equal("8.47457627118644%")
28 | expect(noAtstyles.marginLeft).to.equal("0%")
29 | expect(styles.width).to.equal(noAtstyles.width)
30 |
31 | it 'should set marginRight to one gutter width by default', ->
32 | styles = spanCalculate({columns: 3})
33 |
34 | expect(styles.marginRight).to.equal("1.694915254237288%")
35 |
36 | it 'should remove marginRight if last prop', ->
37 | styles = spanCalculate({last: true})
38 | expect(styles.marginRight).to.equal("0%")
39 |
40 | it 'should float left by default', ->
41 | styles = spanCalculate()
42 | expect(styles.float).to.equal("left")
43 |
44 | it 'should float right if last prop', ->
45 | styles = spanCalculate({last: true})
46 | expect(styles.float).to.equal("right")
47 |
48 | it 'should set "clear:both" if break passed in', ->
49 | styles = spanCalculate({break: true})
50 |
51 | expect(styles.clear).to.equal("both")
52 |
53 | it 'should add marginLeft if pre is not 0', ->
54 | styles = spanCalculate({pre: 3, columns: 3})
55 | noPrestyles = spanCalculate({pre: 0, columns: 3})
56 |
57 | expect(noPrestyles.marginLeft).to.equal("0%")
58 | expect(styles.width).to.equal(noPrestyles.width)
59 | expect(styles.marginLeft).to.not.equal(noPrestyles.marginLeft)
60 |
61 | it 'should add marginRight if post is not 0', ->
62 | styles = spanCalculate({post: 1, columns: 1})
63 | noPoststyles = spanCalculate({post: 0, columns: 1})
64 |
65 | expect(styles.width).to.equal(noPoststyles.width)
66 | expect(styles.marginRight).to.not.equal(noPoststyles.marginRight)
67 |
68 | it 'should produce the same output for marginRight/marginLeft
69 | for squish as it does for pre/post', ->
70 | preStyles = spanCalculate({pre: 1, columns: 1})
71 | postStyles = spanCalculate({post: 1, columns: 1})
72 | squishStyles = spanCalculate({squish: 1, columns: 1})
73 |
74 | expect(postStyles.marginRight).to.equal(squishStyles.marginRight)
75 | expect(preStyles.marginLeft).to.equal(squishStyles.marginLeft)
76 |
77 | it 'should add marginLeft if squish is not 0', ->
78 | styles = spanCalculate({squish: 3, columns: 3})
79 | noSquishstyles = spanCalculate({squish: 0, columns: 3})
80 |
81 | expect(noSquishstyles.marginLeft).to.equal("0%")
82 | expect(styles.width).to.equal(noSquishstyles.width)
83 | expect(styles.marginLeft).to.not.equal(noSquishstyles.marginLeft)
84 |
85 | it 'should eliminate extra right gutter if span is last', ->
86 | styles = spanCalculate({squish: 1, columns: 3, last: true})
87 |
88 | expect(styles.marginLeft).to.equal(styles.marginRight)
89 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 | module.exports = {
5 | entry: [
6 | "webpack-dev-server/client?http://0.0.0.0:8080",
7 | 'webpack/hot/only-dev-server',
8 | './examples/Router'
9 | ],
10 | devServer: {
11 | contentBase: './examples/',
12 | hot: true
13 | },
14 | devtool: "eval",
15 | debug: true,
16 | output: {
17 | path: path.join(__dirname, 'examples'),
18 | filename: 'bundle.js',
19 | },
20 | resolveLoader: {
21 | modulesDirectories: ['node_modules']
22 | },
23 | plugins: [
24 | new webpack.HotModuleReplacementPlugin(),
25 | new webpack.NoErrorsPlugin(),
26 | new webpack.IgnorePlugin(/un~$/)
27 | ],
28 | resolve: {
29 | extensions: ['', '.js', '.cjsx', '.coffee']
30 | },
31 | module: {
32 | loaders: [
33 | { test: /\.css$/, loaders: ['style', 'css']},
34 | { test: /\.cjsx$/, loaders: ['react-hot', 'coffee', 'cjsx']},
35 | { test: /\.coffee$/, loader: 'coffee' }
36 | ]
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/webpack.config.production.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 |
4 |
5 | module.exports = {
6 | entry: [
7 | './examples/Router'
8 | ],
9 | output: {
10 | path: path.join(__dirname, 'examples'),
11 | filename: 'bundle.js',
12 | },
13 | resolveLoader: {
14 | modulesDirectories: ['node_modules']
15 | },
16 | plugins: [
17 | new webpack.DefinePlugin({
18 | "process.env": {
19 | NODE_ENV: JSON.stringify("production")
20 | }
21 | }),
22 | new webpack.optimize.DedupePlugin(),
23 | new webpack.optimize.UglifyJsPlugin()
24 | ],
25 | resolve: {
26 | extensions: ['', '.js', '.cjsx', '.coffee']
27 | },
28 | module: {
29 | loaders: [
30 | { test: /\.css$/, loaders: ['style', 'css']},
31 | { test: /\.cjsx$/, loaders: ['coffee', 'cjsx']},
32 | { test: /\.coffee$/, loader: 'coffee' }
33 | ]
34 | }
35 | };
36 |
--------------------------------------------------------------------------------