react-grid-layout
Advanced tools
Comparing version 0.4.0 to 0.5.0
@@ -6,3 +6,3 @@ "use strict"; | ||
var Resizable = require("react-resizable").Resizable; | ||
var PureDeepRenderMixin = require("./PureDeepRenderMixin"); | ||
var PureDeepRenderMixin = require("./mixins/PureDeepRenderMixin"); | ||
@@ -9,0 +9,0 @@ /** |
@@ -18,10 +18,11 @@ "use strict"; | ||
var utils = require("./utils"); | ||
var PureDeepRenderMixin = require("./PureDeepRenderMixin"); | ||
var PureDeepRenderMixin = require("./mixins/PureDeepRenderMixin"); | ||
var WidthListeningMixin = require("./mixins/WidthListeningMixin"); | ||
/** | ||
* A reactive, fluid, responsive grid layout with draggable, resizable components. | ||
* A reactive, fluid grid layout with draggable, resizable components. | ||
*/ | ||
var ReactGridLayout = React.createClass({ | ||
displayName: "ReactGridLayout", | ||
mixins: [PureDeepRenderMixin], | ||
mixins: [PureDeepRenderMixin, WidthListeningMixin], | ||
@@ -35,30 +36,20 @@ propTypes: { | ||
autoSize: React.PropTypes.bool, | ||
// {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480} | ||
breakpoints: React.PropTypes.object, | ||
// # of cols. Can be specified as a single number, or a breakpoint -> cols map | ||
cols: React.PropTypes.oneOfType([React.PropTypes.object, React.PropTypes.number]), | ||
// # of cols. | ||
cols: React.PropTypes.number, | ||
// A selector for the draggable handler | ||
handle: React.PropTypes.string, | ||
// initialLayout is an array of object with the format: | ||
// layout is an array of object with the format: | ||
// {x: Number, y: Number, w: Number, h: Number} | ||
initialLayout: function (props, propName, componentName) { | ||
var layout = props.initialLayout; | ||
layout: function (props, propName, componentName) { | ||
var layout = props.layout; | ||
// I hope you're setting the on the grid items | ||
if (layout === undefined) return; | ||
utils.validateLayout(layout, "initialLayout"); | ||
utils.validateLayout(layout, "layout"); | ||
}, | ||
// initialLayouts is an object mapping breakpoints to layouts. | ||
// e.g. {lg: Layout, md: Layout, ...} | ||
initialLayouts: function (props, propName, componentName) { | ||
var layouts = props.initialLayouts; | ||
if (layouts === undefined) return; | ||
Object.keys(layouts).map(function (k) { | ||
utils.validateLayout(layouts[k], "initialLayouts." + k); | ||
}); | ||
layouts: function (props, propName, componentName) { | ||
if (props.layouts) throw new Error("ReactGridLayout does not use `layouts`: Use ReactGridLayout.Responsive."); | ||
}, | ||
// This allows setting this on the server side | ||
initialWidth: React.PropTypes.number, | ||
// margin between items [x, y] in px | ||
@@ -75,6 +66,2 @@ margin: React.PropTypes.array, | ||
// If false, you should supply width yourself. Good if you want to debounce resize events | ||
// or reuse a handler from somewhere else. | ||
listenToWindowResize: React.PropTypes.bool, | ||
// | ||
@@ -84,5 +71,2 @@ // Callbacks | ||
// Calls back with breakpoint and new # cols | ||
onBreakpointChange: React.PropTypes.func, | ||
// Callback so you can save the layout. | ||
@@ -117,13 +101,8 @@ // Calls back with (currentLayout, allLayouts). allLayouts are keyed by breakpoint. | ||
autoSize: true, | ||
breakpoints: { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }, | ||
cols: 12, | ||
rowHeight: 150, | ||
initialLayout: [], | ||
initialLayouts: {}, | ||
initialWidth: 1280, | ||
layout: [], | ||
margin: [10, 10], | ||
isDraggable: true, | ||
isResizable: true, | ||
listenToWindowResize: true, | ||
onBreakpointChange: function () {}, | ||
onLayoutChange: function () {} | ||
@@ -134,14 +113,4 @@ }; | ||
getInitialState: function () { | ||
var breakpoint = utils.getBreakpointFromWidth(this.props.breakpoints, this.props.initialWidth); | ||
var cols = this.getColsFromBreakpoint(breakpoint); | ||
var initialLayout = this.props.initialLayout; | ||
if (this.props.initialLayouts && this.props.initialLayouts[breakpoint]) { | ||
initialLayout = this.props.initialLayouts[breakpoint]; | ||
} | ||
return { | ||
layout: utils.synchronizeLayoutWithChildren(initialLayout, this.props.children, cols), | ||
// storage for layouts obsoleted by breakpoints | ||
layouts: this.props.initialLayouts || {}, | ||
breakpoint: breakpoint, | ||
cols: cols, | ||
layout: utils.synchronizeLayoutWithChildren(this.props.layout, this.props.children, this.props.cols), | ||
width: this.props.initialWidth, | ||
@@ -153,13 +122,5 @@ activeDrag: null | ||
componentDidMount: function () { | ||
if (this.props.listenToWindowResize) { | ||
window.addEventListener("resize", this.onWindowResize); | ||
} | ||
// This is intentional. Once to properly set the breakpoint and resize the elements, | ||
// and again to compensate for any scrollbar that appeared because of the first step. | ||
this.onWindowResize(); | ||
this.onWindowResize(); | ||
// Call back with layout on mount. This should be done after correcting the layout width | ||
// to ensure we don't rerender with the wrong width. | ||
this.props.onLayoutChange(this.state.layout, this.state.layouts); | ||
this.props.onLayoutChange(this.state.layout); | ||
}, | ||
@@ -170,3 +131,3 @@ | ||
// Use manual width changes in combination with `listenToWindowResize: false` | ||
if (nextProps.width) this.onWidthChange(nextProps.width); | ||
if (nextProps.width !== this.props.width) this.onWidthChange(nextProps.width); | ||
@@ -176,3 +137,3 @@ // If children change, regenerate the layout. | ||
this.setState({ | ||
layout: utils.synchronizeLayoutWithChildren(this.state.layout, nextProps.children, this.state.cols) | ||
layout: utils.synchronizeLayoutWithChildren(this.state.layout, nextProps.children, nextProps.cols) | ||
}); | ||
@@ -182,5 +143,5 @@ } | ||
// Allow parent to set layout directly. | ||
if (nextProps.layout && nextProps.layout !== this.state.layout) { | ||
if (nextProps.layout && JSON.stringify(nextProps.layout) !== JSON.stringify(this.state.layout)) { | ||
this.setState({ | ||
layout: utils.synchronizeLayoutWithChildren(nextProps.layout, nextProps.children, this.state.cols) | ||
layout: utils.synchronizeLayoutWithChildren(nextProps.layout, nextProps.children, nextProps.cols) | ||
}); | ||
@@ -190,6 +151,2 @@ } | ||
componentWillUnmount: function () { | ||
window.removeEventListener("resize", this.onWindowResize); | ||
}, | ||
componentDidUpdate: function (prevProps, prevState) { | ||
@@ -212,52 +169,7 @@ // Call back so we can store the layout | ||
getColsFromBreakpoint: function (breakpoint) { | ||
var cols = this.props.cols; | ||
if (typeof cols === "number") return cols; | ||
if (!cols[breakpoint]) { | ||
throw new Error("ReactGridLayout: `cols` entry for breakpoint " + breakpoint + " is missing!"); | ||
} | ||
return cols[breakpoint]; | ||
}, | ||
/** | ||
* On window resize, update width. | ||
* When the width changes, save it to state. This helps with left/width calculations. | ||
*/ | ||
onWindowResize: function () { | ||
this.onWidthChange(this.getDOMNode().offsetWidth); | ||
}, | ||
/** | ||
* When the width changes work through breakpoints and reset state with the new width & breakpoint. | ||
* Width changes are necessary to figure out the widget widths. | ||
*/ | ||
onWidthChange: function (width) { | ||
// Set new breakpoint | ||
var newState = { width: width }; | ||
newState.breakpoint = utils.getBreakpointFromWidth(this.props.breakpoints, newState.width); | ||
newState.cols = this.getColsFromBreakpoint(newState.breakpoint); | ||
// Breakpoint change | ||
if (newState.cols !== this.state.cols) { | ||
// Store the current layout | ||
newState.layouts = this.state.layouts; | ||
newState.layouts[this.state.breakpoint] = JSON.parse(JSON.stringify(this.state.layout)); | ||
// Find or generate a new one. | ||
newState.layout = newState.layouts[newState.breakpoint]; | ||
if (!newState.layout) { | ||
newState.layout = utils.newResponsiveLayout(newState.layouts, this.props.breakpoints, newState.breakpoint, this.state.breakpoint, newState.cols); | ||
} | ||
// This adds missing items. | ||
newState.layout = utils.synchronizeLayoutWithChildren(newState.layout, this.props.children, newState.cols); | ||
// Store this new layout as well. | ||
newState.layouts[newState.breakpoint] = newState.layout; | ||
} | ||
if (newState.cols !== this.state.cols) { | ||
this.props.onBreakpointChange(newState.breakpoint, newState.cols); | ||
} | ||
this.setState(newState); | ||
this.setState({ width: width }); | ||
}, | ||
@@ -343,3 +255,3 @@ | ||
containerWidth: this.state.width, | ||
cols: this.state.cols, | ||
cols: this.props.cols, | ||
margin: this.props.margin, | ||
@@ -373,3 +285,3 @@ rowHeight: this.props.rowHeight, | ||
containerWidth: this.state.width, | ||
cols: this.state.cols, | ||
cols: this.props.cols, | ||
margin: this.props.margin, | ||
@@ -376,0 +288,0 @@ rowHeight: this.props.rowHeight, |
@@ -44,5 +44,6 @@ "use strict"; | ||
compact: function (layout) { | ||
// Statics go in the compareWith array right away so items flow around them. | ||
var compareWith = utils.getStatics(layout), out = []; | ||
// We go through the items by row and column. | ||
var compareWith = [], out = []; | ||
var sorted = utils.getLayoutItemsByRowCol(layout); | ||
var sorted = utils.sortLayoutItemsByRowCol(layout); | ||
@@ -55,7 +56,8 @@ for (var i = 0, len = sorted.length; i < len; i++) { | ||
l = utils.compactItem(compareWith, l); | ||
// Add to comparison array. We only collide with items before this one. | ||
// Statics are already in this array. | ||
compareWith.push(l); | ||
} | ||
// Add to comparison array. We only collide with items before this one. | ||
compareWith.push(l); | ||
// Add to output array to make sure they still come out in the right order. | ||
@@ -93,2 +95,3 @@ out[layout.indexOf(l)] = l; | ||
correctBounds: function (layout, bounds) { | ||
var collidesWith = utils.getStatics(layout); | ||
for (var i = 0, len = layout.length; i < len; i++) { | ||
@@ -103,2 +106,9 @@ var l = layout[i]; | ||
} | ||
if (!l["static"]) collidesWith.push(l);else { | ||
// If this is static and collides with other statics, we must move it down. | ||
// We have to do something nicer than just letting them overlap. | ||
while (utils.getFirstCollision(collidesWith, l)) { | ||
l.y++; | ||
} | ||
} | ||
} | ||
@@ -109,19 +119,2 @@ return layout; | ||
/** | ||
* Given a width, find the highest breakpoint that matches is valid for it (width > breakpoint). | ||
* | ||
* @param {Object} breakpoints Breakpoints object (e.g. {lg: 1200, md: 960, ...}) | ||
* @param {Number} width Screen width. | ||
* @return {String} Highest breakpoint that is less than width. | ||
*/ | ||
getBreakpointFromWidth: function (breakpoints, width) { | ||
var sorted = utils.sortBreakpoints(breakpoints); | ||
var matching = sorted[0]; | ||
for (var i = 1, len = sorted.length; i < len; i++) { | ||
var breakpointName = sorted[i]; | ||
if (width > breakpoints[breakpointName]) matching = breakpointName; | ||
} | ||
return matching; | ||
}, | ||
/** | ||
* Get a layout item by ID. Used so we can override later on if necessary. | ||
@@ -141,16 +134,2 @@ * | ||
/** | ||
* Get layout items sorted from top left to right and down. | ||
* | ||
* @return {Array} Array of layout objects. | ||
*/ | ||
getLayoutItemsByRowCol: function (layout) { | ||
return [].concat(layout).sort(function (a, b) { | ||
if (a.y > b.y || a.y === b.y && a.x > b.x) { | ||
return 1; | ||
} | ||
return -1; | ||
}); | ||
}, | ||
/** | ||
* Returns the first item this layout collides with. | ||
@@ -178,2 +157,15 @@ * It doesn't appear to matter which order we approach this from, although | ||
/** | ||
* Get all static elements. | ||
* @param {Array} layout Array of layout objects. | ||
* @return {Array} Array of static layout items.. | ||
*/ | ||
getStatics: function (layout) { | ||
var out = []; | ||
for (var i = 0, len = layout.length; i < len; i++) { | ||
if (layout[i]["static"]) out.push(layout[i]); | ||
} | ||
return out; | ||
}, | ||
/** | ||
* Move an element. Responsible for doing cascading movements of other elements. | ||
@@ -204,3 +196,3 @@ * | ||
// nearest collision. | ||
var sorted = utils.getLayoutItemsByRowCol(layout); | ||
var sorted = utils.sortLayoutItemsByRowCol(layout); | ||
if (movingUp) sorted = sorted.reverse(); | ||
@@ -264,29 +256,2 @@ var collisions = utils.getAllCollisions(sorted, l); | ||
/** | ||
* Given existing layouts and a new breakpoint, generate a new layout. | ||
* This finds the layout above the new one and generates from it, if it exists. | ||
* | ||
* @param {Array} layouts Existing layouts. | ||
* @param {Array} breakpoints All breakpoints. | ||
* @param {String} breakpoint New breakpoint. | ||
* @param {String} breakpoint Last breakpoint (for fallback). | ||
* @param {Number} cols Column count at new breakpoint. | ||
* @return {Array} New layout. | ||
*/ | ||
newResponsiveLayout: function (layouts, breakpoints, breakpoint, lastBreakpoint, cols) { | ||
// Find or generate the next layout | ||
var layout = layouts[lastBreakpoint]; | ||
var breakpointsSorted = utils.sortBreakpoints(breakpoints); | ||
var breakpointsAbove = breakpointsSorted.slice(breakpointsSorted.indexOf(breakpoint)); | ||
for (var i = 0, len = breakpointsAbove.length; i < len; i++) { | ||
var b = breakpointsAbove[i]; | ||
if (layouts[b]) { | ||
layout = layouts[b]; | ||
break; | ||
} | ||
} | ||
layout = JSON.parse(JSON.stringify(layout)); // clone layout so we don't modify existing items | ||
return utils.compact(utils.correctBounds(layout, { cols: cols })); | ||
}, | ||
/** | ||
* Helper to convert a number to a percentage string. | ||
@@ -302,12 +267,13 @@ * | ||
/** | ||
* Given breakpoints, return an array of breakpoints sorted by width. This is usually | ||
* e.g. ['xxs', 'xs', 'sm', ...] | ||
* Get layout items sorted from top left to right and down. | ||
* | ||
* @param {Object} breakpoints Key/value pair of breakpoint names to widths. | ||
* @return {Array} Sorted breakpoints. | ||
* @return {Array} Array of layout objects. | ||
* @return {Array} Layout, sorted static items first. | ||
*/ | ||
sortBreakpoints: function (breakpoints) { | ||
var keys = Object.keys(breakpoints); | ||
return keys.sort(function (a, b) { | ||
return breakpoints[a] - breakpoints[b]; | ||
sortLayoutItemsByRowCol: function (layout) { | ||
return [].concat(layout).sort(function (a, b) { | ||
if (a.y > b.y || a.y === b.y && a.x > b.x) { | ||
return 1; | ||
} | ||
return -1; | ||
}); | ||
@@ -314,0 +280,0 @@ }, |
module.exports = require('./build/ReactGridLayout'); | ||
module.exports.Responsive = require('./build/ResponsiveReactGridLayout'); |
{ | ||
"name": "react-grid-layout", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "A draggable and resizable grid layout with responsive breakpoints, for React.", | ||
@@ -12,3 +12,3 @@ "main": "index.js", | ||
"check-build": "make check-build", | ||
"dev-server": "echo 'Open http://localhost:4002'; webpack-dev-server --config webpack-dev-server.config.js --hot --progress --colors --port 4002 --content-base ." | ||
"dev": "echo 'Open http://localhost:4002'; webpack-dev-server --config webpack-dev-server.config.js --hot --progress --colors --port 4002 --content-base ." | ||
}, | ||
@@ -44,2 +44,3 @@ "repository": { | ||
"css-loader": "^0.9.0", | ||
"ejs": "^1.0.0", | ||
"exports-loader": "^0.6.2", | ||
@@ -46,0 +47,0 @@ "imports-loader": "^0.6.3", |
@@ -20,3 +20,3 @@ # React-Grid-Layout | ||
[View the Demo](https://strml.github.io/react-grid-layout/examples/1-basic.html) | ||
[View the Demo](https://strml.github.io/react-grid-layout/examples/0-showcase.html) | ||
@@ -35,2 +35,3 @@ React-Grid-Layout is a grid layout system much like [Packery](http://packery.metafizzy.co/) or | ||
1. [Showcase](https://strml.github.io/react-grid-layout/examples/0-showcase.html) | ||
1. [Basic](https://strml.github.io/react-grid-layout/examples/1-basic.html) | ||
@@ -64,8 +65,9 @@ 1. [No Dragging/Resizing (Layout Only)](https://strml.github.io/react-grid-layout/examples/2-no-dragging.html) | ||
```javascript | ||
var ReactGridLayout = require('react-grid-layout'); | ||
//... | ||
render: function() { | ||
// layout is an array of objects, see the demo | ||
var initialLayout = getOrGenerateLayout(); | ||
var layout = getOrGenerateLayout(); | ||
return ( | ||
<ReactGridLayout className="layout" initialLayout={initialLayout} | ||
<ReactGridLayout className="layout" layout={layout} | ||
cols={12} rowHeight={30}> | ||
@@ -78,3 +80,2 @@ <div key={1}>1</div> | ||
} | ||
``` | ||
@@ -86,3 +87,4 @@ | ||
```javascript | ||
var ReactGridLayout = require('react-grid-layout'); | ||
//... | ||
render: function() { | ||
@@ -97,3 +99,2 @@ return ( | ||
} | ||
``` | ||
@@ -103,9 +104,12 @@ | ||
To make RGL responsive, supply a map as the `cols` prop: | ||
To make RGL responsive, use the `<ResponsiveReactGridLayout>` element: | ||
```javascript | ||
var ResponsiveReactGridLayout = require('react-grid-layout').Responsive; | ||
//... | ||
render: function() { | ||
// {lg: layout1, md: layout2, ...} | ||
var layouts = getLayoutsFromSomewhere(); | ||
return ( | ||
<ReactGridLayout className="layout" initialLayouts={...} | ||
<ResponsiveReactGridLayout className="layout" layouts={layouts} | ||
cols={{lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}}> | ||
@@ -115,3 +119,3 @@ <div key={1}>1</div> | ||
<div key={3}>3</div> | ||
</ReactGridLayout> | ||
</ResponsiveReactGridLayout> | ||
) | ||
@@ -121,6 +125,5 @@ } | ||
You have a choice when in responsive mode: you can simply supply an single layout | ||
via `initialLayout`, or multiple layouts in a map via `initialLayouts`. | ||
When in responsive mode, you should supply at least one breakpoint via the `layouts` property. | ||
When using `initialLayouts`, it is best to supply as many breakpoints as possible, especially the largest one. | ||
When using `layouts`, it is best to supply as many breakpoints as possible, especially the largest one. | ||
If the largest is provided, RGL will attempt to interpolate the rest. | ||
@@ -147,9 +150,4 @@ | ||
// Can be specified as a single number or a {breakpoint: cols} map. | ||
// If a map is provided, RGL becomes responsive and uses a separate layout | ||
// per breakpoint. | ||
cols: React.PropTypes.oneOfType([ | ||
React.PropTypes.object, | ||
React.PropTypes.number | ||
]), | ||
// Number of columns in this layout. | ||
cols: React.PropTypes.number, | ||
@@ -161,8 +159,4 @@ // A selector for the draggable handler | ||
// {x: Number, y: Number, w: Number, h: Number} | ||
initialLayout: React.PropTypes.array, | ||
layout: React.PropTypes.array, | ||
// initialLayouts is an object mapping breakpoints to layouts. | ||
// e.g. {lg: Layout, md: Layout, ...} | ||
initialLayouts: React.PropTypes.object, | ||
// This allows setting this on the server side | ||
@@ -192,2 +186,28 @@ initialWidth: React.PropTypes.number, | ||
// Callback so you can save the layout. | ||
// Calls back with (currentLayout, allLayouts). allLayouts are keyed by breakpoint. | ||
onLayoutChange: React.PropTypes.func, | ||
``` | ||
#### Responsive Grid Layout Props | ||
The responsive grid layout can be used instead. It supports all of the props above, excepting `layout`. | ||
The new properties and changes are: | ||
```javascript | ||
// {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480} | ||
// Breakpoint names are arbitrary but must match in the cols and layouts objects. | ||
breakpoints: React.PropTypes.object, | ||
// # of cols. This is a breakpoint -> cols map, e.g. {lg: 12, md: 10, ...} | ||
cols: React.PropTypes.object, | ||
// layouts is an object mapping breakpoints to layouts. | ||
// e.g. {lg: Layout, md: Layout, ...} | ||
layouts: React.PropTypes.object | ||
// | ||
// Callbacks | ||
// | ||
// Calls back with breakpoint and new # cols | ||
@@ -198,3 +218,3 @@ onBreakpointChange: React.PropTypes.func, | ||
// Calls back with (currentLayout, allLayouts). allLayouts are keyed by breakpoint. | ||
onLayoutChange: React.PropTypes.func, | ||
onLayoutChange: React.PropTypes.func | ||
``` | ||
@@ -201,0 +221,0 @@ |
@@ -34,4 +34,6 @@ var webpack = require("webpack"); | ||
extensions: ["", ".webpack.js", ".web.js", ".js", ".jsx"], | ||
alias: {'react-grid-layout': __dirname + '/lib/ReactGridLayout.jsx'} | ||
alias: { | ||
'react-grid-layout': __dirname + '/index-dev.js' | ||
} | ||
} | ||
}; |
@@ -37,3 +37,3 @@ 'use strict'; | ||
extensions: ["", ".webpack.js", ".web.js", ".js", ".jsx"], | ||
alias: {'react-grid-layout': __dirname + '/lib/ReactGridLayout.jsx'} | ||
alias: {'react-grid-layout': __dirname + '/index-dev.js'} | ||
} | ||
@@ -40,0 +40,0 @@ }; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
54748
20
1182
259
14