Giter Site home page Giter Site logo

react-grid-layout / react-grid-layout Goto Github PK

View Code? Open in Web Editor NEW
19.5K 19.5K 2.5K 15 MB

A draggable and resizable grid layout with responsive breakpoints, for React.

Home Page: https://react-grid-layout.github.io/react-grid-layout/examples/0-showcase.html

License: MIT License

CSS 1.24% JavaScript 97.47% HTML 0.26% Makefile 1.00% Shell 0.04%
drag-and-drop es2015 grid javascript react resize

react-grid-layout's Introduction

React-Grid-Layout

travis build CDNJS npm package npm downloads

React-Grid-Layout is a grid layout system much like Packery or Gridster, for React.

Unlike those systems, it is responsive and supports breakpoints. Breakpoint layouts can be provided by the user or autogenerated.

RGL is React-only and does not require jQuery.

BitMEX UI

GIF from production usage on BitMEX.com

[Demo | Changelog | CodeSandbox Editable demo]

Table of Contents

Demos

  1. Showcase
  2. Basic
  3. No Dragging/Resizing (Layout Only)
  4. Messy Layout Autocorrect
  5. Layout Defined on Children
  6. Static Elements
  7. Adding/Removing Elements
  8. Saving Layout to LocalStorage
  9. Saving a Responsive Layout to LocalStorage
  10. Minimum and Maximum Width/Height
  11. Dynamic Minimum and Maximum Width/Height
  12. No Vertical Compacting (Free Movement)
  13. Prevent Collision
  14. Error Case
  15. Toolbox
  16. Drag From Outside
  17. Bounded Layout
  18. Resizable Handles
  19. Scaled Containers
  20. Allow Overlap
  21. All Resizable Handles
  22. Single Row Horizontal

Projects Using React-Grid-Layout

Know of others? Create a PR to let me know!

Features

  • 100% React - no jQuery
  • Compatible with server-rendered apps
  • Draggable widgets
  • Resizable widgets
  • Static widgets
  • Configurable packing: horizontal, vertical, or off
  • Bounds checking for dragging and resizing
  • Widgets may be added or removed without rebuilding grid
  • Layout can be serialized and restored
  • Responsive breakpoints
  • Separate layouts per responsive breakpoint
  • Grid Items placed using CSS Transforms
    • Performance with CSS Transforms: on / off, note paint (green) as % of time
  • Compatibility with <React.StrictMode>
Version Compatibility
>= 0.17.0 React 16 & 17
>= 0.11.3 React 0.14 & 15
>= 0.10.0 React 0.14
0.8. - 0.9.2 React 0.13
< 0.8 React 0.12

Installation

Install the React-Grid-Layout package using npm:

npm install react-grid-layout

Include the following stylesheets in your application:

/node_modules/react-grid-layout/css/styles.css
/node_modules/react-resizable/css/styles.css

Usage

Use ReactGridLayout like any other component. The following example below will produce a grid with three items where:

  • users will not be able to drag or resize item a
  • item b will be restricted to a minimum width of 2 grid blocks and a maximum width of 4 grid blocks
  • users will be able to freely drag and resize item c
import GridLayout from "react-grid-layout";

class MyFirstGrid extends React.Component {
  render() {
    // layout is an array of objects, see the demo for more complete usage
    const layout = [
      { i: "a", x: 0, y: 0, w: 1, h: 2, static: true },
      { i: "b", x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },
      { i: "c", x: 4, y: 0, w: 1, h: 2 }
    ];
    return (
      <GridLayout
        className="layout"
        layout={layout}
        cols={12}
        rowHeight={30}
        width={1200}
      >
        <div key="a">a</div>
        <div key="b">b</div>
        <div key="c">c</div>
      </GridLayout>
    );
  }
}

You may also choose to set layout properties directly on the children:

import GridLayout from "react-grid-layout";

class MyFirstGrid extends React.Component {
  render() {
    return (
      <GridLayout className="layout" cols={12} rowHeight={30} width={1200}>
        <div key="a" data-grid={{ x: 0, y: 0, w: 1, h: 2, static: true }}>
          a
        </div>
        <div key="b" data-grid={{ x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }}>
          b
        </div>
        <div key="c" data-grid={{ x: 4, y: 0, w: 1, h: 2 }}>
          c
        </div>
      </GridLayout>
    );
  }
}

Usage without Browserify/Webpack

A module usable in a <script> tag is included here. It uses a UMD shim and excludes React, so it must be otherwise available in your application, either via RequireJS or on window.React.

Responsive Usage

To make RGL responsive, use the <ResponsiveReactGridLayout> element:

import { Responsive as ResponsiveGridLayout } from "react-grid-layout";

class MyResponsiveGrid extends React.Component {
  render() {
    // {lg: layout1, md: layout2, ...}
    const layouts = getLayoutsFromSomewhere();
    return (
      <ResponsiveGridLayout
        className="layout"
        layouts={layouts}
        breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
        cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
      >
        <div key="1">1</div>
        <div key="2">2</div>
        <div key="3">3</div>
      </ResponsiveGridLayout>
    );
  }
}

When in responsive mode, you should supply at least one breakpoint via the layouts property.

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.

You will also need to provide a width, when using <ResponsiveReactGridLayout> it is suggested you use the HOC WidthProvider as per the instructions below.

It is possible to supply default mappings via the data-grid property on individual items, so that they would be taken into account within layout interpolation.

Providing Grid Width

Both <ResponsiveReactGridLayout> and <ReactGridLayout> take width to calculate positions on drag events. In simple cases a HOC WidthProvider can be used to automatically determine width upon initialization and window resize events.

import { Responsive, WidthProvider } from "react-grid-layout";

const ResponsiveGridLayout = WidthProvider(Responsive);

class MyResponsiveGrid extends React.Component {
  render() {
    // {lg: layout1, md: layout2, ...}
    var layouts = getLayoutsFromSomewhere();
    return (
      <ResponsiveGridLayout
        className="layout"
        layouts={layouts}
        breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
        cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
      >
        <div key="1">1</div>
        <div key="2">2</div>
        <div key="3">3</div>
      </ResponsiveGridLayout>
    );
  }
}

This allows you to easily replace WidthProvider with your own Provider HOC if you need more sophisticated logic.

WidthProvider accepts a single prop, measureBeforeMount. If true, WidthProvider will measure the container's width before mounting children. Use this if you'd like to completely eliminate any resizing animation on application/component mount.

Have a more complicated layout? WidthProvider is very simple and only listens to window 'resize' events. If you need more power and flexibility, try the SizeMe React HOC as an alternative to WidthProvider.

Grid Layout Props

RGL supports the following properties (see the source for the final word on this):

//
// Basic props
//

// This allows setting the initial width on the server side.
// This is required unless using the HOC <WidthProvider> or similar
width: number,

// If true, the container height swells and contracts to fit contents
autoSize: ?boolean = true,

// Number of columns in this layout.
cols: ?number = 12,

// A CSS selector for tags that will not be draggable.
// For example: draggableCancel:'.MyNonDraggableAreaClassName'
// If you forget the leading . it will not work.
// .react-resizable-handle" is always prepended to this value.
draggableCancel: ?string = '',

// A CSS selector for tags that will act as the draggable handle.
// For example: draggableHandle:'.MyDragHandleClassName'
// If you forget the leading . it will not work.
draggableHandle: ?string = '',

// Compaction type.
compactType: ?('vertical' | 'horizontal' | null) = 'vertical';

// Layout is an array of object with the format:
// {x: number, y: number, w: number, h: number}
// The index into the layout must match the key used on each item component.
// If you choose to use custom keys, you can specify that key in the layout
// array objects like so:
// {i: string, x: number, y: number, w: number, h: number}
layout: ?array = null, // If not provided, use data-grid props on children

// Margin between items [x, y] in px.
margin: ?[number, number] = [10, 10],

// Padding inside the container [x, y] in px
containerPadding: ?[number, number] = margin,

// Rows have a static height, but you can change this based on breakpoints
// if you like.
rowHeight: ?number = 150,

// Configuration of a dropping element. Dropping element is a "virtual" element
// which appears when you drag over some element from outside.
// It can be changed by passing specific parameters:
//  i - id of an element
//  w - width of an element
//  h - height of an element
droppingItem?: { i: string, w: number, h: number }

//
// Flags
//
isDraggable: ?boolean = true,
isResizable: ?boolean = true,
isBounded: ?boolean = false,
// Uses CSS3 translate() instead of position top/left.
// This makes about 6x faster paint performance
useCSSTransforms: ?boolean = true,
// If parent DOM node of ResponsiveReactGridLayout or ReactGridLayout has "transform: scale(n)" css property,
// we should set scale coefficient to avoid render artefacts while dragging.
transformScale: ?number = 1,

// If true, grid can be placed one over the other.
// If set, implies `preventCollision`.
allowOverlap: ?boolean = false,

// If true, grid items won't change position when being
// dragged over. If `allowOverlap` is still false,
// this simply won't allow one to drop on an existing object.
preventCollision: ?boolean = false,

// If true, droppable elements (with `draggable={true}` attribute)
// can be dropped on the grid. It triggers "onDrop" callback
// with position and event object as parameters.
// It can be useful for dropping an element in a specific position
//
// NOTE: In case of using Firefox you should add
// `onDragStart={e => e.dataTransfer.setData('text/plain', '')}` attribute
// along with `draggable={true}` otherwise this feature will work incorrect.
// onDragStart attribute is required for Firefox for a dragging initialization
// @see https://bugzilla.mozilla.org/show_bug.cgi?id=568313
isDroppable: ?boolean = false,
// Defines which resize handles should be rendered.
// Allows for any combination of:
// 's' - South handle (bottom-center)
// 'w' - West handle (left-center)
// 'e' - East handle (right-center)
// 'n' - North handle (top-center)
// 'sw' - Southwest handle (bottom-left)
// 'nw' - Northwest handle (top-left)
// 'se' - Southeast handle (bottom-right)
// 'ne' - Northeast handle (top-right)
//
// Note that changing this property dynamically does not work due to a restriction in react-resizable.
resizeHandles: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se'],
// Custom component for resize handles
// See `handle` as used in https://github.com/react-grid-layout/react-resizable#resize-handle
// Your component should have the class `.react-resizable-handle`, or you should add your custom
// class to the `draggableCancel` prop.
resizeHandle?: ReactElement<any> | ((resizeHandleAxis: ResizeHandleAxis, ref: ReactRef<HTMLElement>) => ReactElement<any>),

//
// Callbacks
//

// Callback so you can save the layout.
// Calls back with (currentLayout) after every drag or resize stop.
onLayoutChange: (layout: Layout) => void,

//
// All callbacks below have signature (layout, oldItem, newItem, placeholder, e, element).
// 'start' and 'stop' callbacks pass `undefined` for 'placeholder'.
//
type ItemCallback = (layout: Layout, oldItem: LayoutItem, newItem: LayoutItem,
                     placeholder: LayoutItem, e: MouseEvent, element: HTMLElement) => void,

// Calls when drag starts.
onDragStart: ItemCallback,
// Calls on each drag movement.
onDrag: ItemCallback,
// Calls when drag is complete.
onDragStop: ItemCallback,
// Calls when resize starts.
onResizeStart: ItemCallback,
// Calls when resize movement happens.
onResize: ItemCallback,
// Calls when resize is complete.
onResizeStop: ItemCallback,

//
// Dropover functionality
//

// Calls when an element has been dropped into the grid from outside.
onDrop: (layout: Layout, item: ?LayoutItem, e: Event) => void,
// Calls when an element is being dragged over the grid from outside as above.
// This callback should return an object to dynamically change the droppingItem size
// Return false to short-circuit the dragover
onDropDragOver: (e: DragOverEvent) => ?({|w?: number, h?: number|} | false),

// Ref for getting a reference for the grid's wrapping div.
// You can use this instead of a regular ref and the deprecated `ReactDOM.findDOMNode()`` function.
// Note that this type is React.Ref<HTMLDivElement> in TypeScript, Flow has a bug here
// https://github.com/facebook/flow/issues/8671#issuecomment-862634865
innerRef: {current: null | HTMLDivElement},

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:

// {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: ?Object = {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0},

// # of cols. This is a breakpoint -> cols map, e.g. {lg: 12, md: 10, ...}
cols: ?Object = {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2},


// margin (in pixels). Can be specified either as horizontal and vertical margin, e.g. `[10, 10]` or as a breakpoint -> margin map, e.g. `{lg: [10, 10], md: [10, 10], ...}.
margin: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]},


// containerPadding (in pixels). Can be specified either as horizontal and vertical padding, e.g. `[10, 10]` or as a breakpoint -> containerPadding map, e.g. `{lg: [10, 10], md: [10, 10], ...}.
containerPadding: [number, number] | {[breakpoint: $Keys<breakpoints>]: [number, number]},


// layouts is an object mapping breakpoints to layouts.
// e.g. {lg: Layout, md: Layout, ...}
layouts: {[key: $Keys<breakpoints>]: Layout},

//
// Callbacks
//

// Calls back with breakpoint and new # cols
onBreakpointChange: (newBreakpoint: string, newCols: number) => void,

// Callback so you can save the layout.
// AllLayouts are keyed by breakpoint.
onLayoutChange: (currentLayout: Layout, allLayouts: {[key: $Keys<breakpoints>]: Layout}) => void,

// Callback when the width changes, so you can modify the layout as needed.
onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) => void;

Grid Item Props

RGL supports the following properties on grid items or layout items. When initializing a grid, build a layout array (as in the first example above), or attach this object as the data-grid property to each of your child elements (as in the second example).

If data-grid is provided on an item, it will take precedence over an item in the layout with the same key (i).

Note that if a grid item is provided but incomplete (missing one of x, y, w, or h), an error will be thrown so you can correct your layout.

If no properties are provided for a grid item, one will be generated with a width and height of 1.

You can set minimums and maximums for each dimension. This is for resizing; it of course has no effect if resizing is disabled. Errors will be thrown if your mins and maxes overlap incorrectly, or your initial dimensions are out of range.

Any <GridItem> properties defined directly will take precedence over globally-set options. For example, if the layout has the property isDraggable: false, but the grid item has the prop isDraggable: true, the item will be draggable, even if the item is marked static: true.

{

  // A string corresponding to the component key
  i: string,

  // These are all in grid units, not pixels
  x: number,
  y: number,
  w: number,
  h: number,
  minW: ?number = 0,
  maxW: ?number = Infinity,
  minH: ?number = 0,
  maxH: ?number = Infinity,

  // If true, equal to `isDraggable: false, isResizable: false`.
  static: ?boolean = false,
  // If false, will not be draggable. Overrides `static`.
  isDraggable: ?boolean = true,
  // If false, will not be resizable. Overrides `static`.
  isResizable: ?boolean = true,
  // By default, a handle is only shown on the bottom-right (southeast) corner.
  // As of RGL >= 1.4.0, resizing on any corner works just fine!
  resizeHandles?: ?Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se']
  // If true and draggable, item will be moved only within grid.
  isBounded: ?boolean = false
}

Grid Item Heights and Widths

Grid item widths are based on container and number of columns. The size of a grid unit's height is based on rowHeight.

Note that an item that has h=2 is not exactly twice as tall as one with h=1 unless you have no margin!

In order for the grid to not be ragged, when an item spans grid units, it must also span margins. So you must add the height or width or the margin you are spanning for each unit. So actual pixel height is (rowHeight * h) + (marginH * (h - 1).

For example, with rowHeight=30, margin=[10,10] and a unit with height 4, the calculation is (30 * 4) + (10 * 3)

margin

If this is a problem for you, set margin=[0,0] and handle visual spacing between your elements inside the elements' content.

Performance

<ReactGridLayout> has an optimized shouldComponentUpdate implementation, but it relies on the user memoizing the children array:

// lib/ReactGridLayout.jsx
// ...
shouldComponentUpdate(nextProps: Props, nextState: State) {
  return (
    // NOTE: this is almost always unequal. Therefore the only way to get better performance
    // from SCU is if the user intentionally memoizes children. If they do, and they can
    // handle changes properly, performance will increase.
    this.props.children !== nextProps.children ||
    !fastRGLPropsEqual(this.props, nextProps, isEqual) ||
    !isEqual(this.state.activeDrag, nextState.activeDrag)
  );
}
// ...

If you memoize your children, you can take advantage of this, and reap faster rerenders. For example:

function MyGrid(props) {
  const children = React.useMemo(() => {
    return new Array(props.count).fill(undefined).map((val, idx) => {
      return <div key={idx} data-grid={{ x: idx, y: 1, w: 1, h: 1 }} />;
    });
  }, [props.count]);
  return <ReactGridLayout cols={12}>{children}</ReactGridLayout>;
}

Because the children prop doesn't change between rerenders, updates to <MyGrid> won't result in new renders, improving performance.

React Hooks Performance

Using hooks to save your layout state on change will cause the layouts to re-render as the ResponsiveGridLayout will change it's value on every render. To avoid this you should wrap your WidthProvider in a useMemo:

const ResponsiveReactGridLayout = useMemo(() => WidthProvider(Responsive), []);

Custom Child Components and Draggable Handles

If you use React Components as grid children, they need to do a few things:

  1. Forward refs to an underlying DOM node, and
  2. Forward style,className, onMouseDown, onMouseUp and onTouchEnd to that same DOM node.

For example:

const CustomGridItemComponent = React.forwardRef(({style, className, onMouseDown, onMouseUp, onTouchEnd, children, ...props}, ref) => {
  return (
    <div style={{ /* styles */, ...style}} className={className} ref={ref} onMouseDown={onMouseDown} onMouseUp={onMouseUp} onTouchEnd={onTouchEnd}>
      {/* Some other content */}
      {children} {/* Make sure to include children to add resizable handle */}
    </div>
  );
})

The same is true of custom elements as draggable handles using the draggableHandle prop. This is so that the underlying react-draggable library can get a reference to the DOM node underneath, manipulate positioning via style, and set classes.

Contribute

If you have a feature request, please add it as an issue or make a pull request.

If you have a bug to report, please reproduce the bug in CodeSandbox to help us easily isolate it.

TODO List

  • Basic grid layout
  • Fluid grid layout
  • Grid packing
  • Draggable grid items
  • Live grid packing while dragging
  • Resizable grid items
  • Layouts per responsive breakpoint
  • Define grid attributes on children themselves (data-grid key)
  • Static elements
  • Persistent id per item for predictable localstorage restores, even when # items changes
  • Min/max w/h per item
  • Resizable handles on other corners
  • Configurable w/h per breakpoint

react-grid-layout's People

Contributors

aweber1 avatar bravo-kernel avatar browniefed avatar cp avatar daynin avatar dseif avatar emrysmyrddin avatar imaginelife avatar larrydahooster avatar mei33 avatar n1ghtmare avatar nikolas avatar rasmushjulskov avatar riid avatar rinick avatar ro-savage avatar rogerfar avatar roshsingh avatar s4m3 avatar salvoravida avatar seanich avatar serebrennikovalex avatar skoging avatar strml avatar sufuf3 avatar thasner avatar torkelo avatar trysound avatar vagoel avatar xcqwan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-grid-layout's Issues

Demos are not working...

Error in the first demo:
Line 67 of 1-basic.bundle.js -> Uncaught TypeError: undefined is not a function

Typos in example

  `<div key={1} _grid={{x: 0, y: 0, w: 1: h: 2}}>1</div>
      <div key={2} _grid={{x: 1, y: 0, w: 1: h: 2}}>2</div>
      <div key={3} _grid={{x: 2, y: 0, w: 1: h: 2}}>3</div>`

3 of those semicolons should be commas

Set row's height ?

is there a way to set the row's height and not depends on its parents height ?

Responsive rowHeight = {120} breakpoints = {{ lg: 1600, md: 1024, sm: 480, xs: 320 }}
cols = {{ lg:12, md: 12, sm: 12, xs: 12}}
div className = "row" key = {5}
img src = "#"
img src = "#"
/div
Responsive

Inner grid gets default width and not parent grid's width

I'm not sure if this is a bug or feature but in any case, help is appreciated :)

My structure is like this:

Grid 1 with 12 columns
    div using all 12 cols
         Grid 12 columns
              ....

Now grid 1 gets the full width of the window but grid 2 for some reason defaults to 1280px. However if I resize the window grid 2 correctly sets itself to grid 1's width.

I tried initialWidth={window.innerWidth} with grid 2 but it politely ignored it and used 1280px.

synchronizeWithChildren fails with child.key undefined error

In utils.js function synchronizeWithChildren starts off

    children = [].concat(children); // ensure 'children' is always an array

If the incoming children argument to this function is undefined, which it will be if you create a ReactGridLayout with none, then the result of this statement is an array, length 1 with children[0] === undefined. The loop over children sets child to this undefined, and throws an exception as soon as it tries to access a property of child.

Can it do variable height?

If you get a chance, would love an example with variable-height images, as in hearsay.me or react.rocks. Basic markup, with Bootstrap:

 <div className="col-lg-3 col-md-4 col-sm-6 col-xs-12">
  <a href={this.getArticleLink()} className='thumbnail article'>
   <img src='whatever'>

Thanks!

onResizeStop arguments not correct

For one, the signature for all the event handlers is undocumented.
Looking at the code for onResizeStop, I believe it should be calling my handler with
0. the current grid layout

  1. the previous layout of the box being resized
  2. the new layout of the box being resized
  3. null
  4. the event
    However,oldL = utils.clone(l), so arguments 1 and 2 are always identical.

TypeError: Cannot set property 'validated' of undefined

Thanks for your great work with this library! I'm new to React and am unfortunately having some trouble getting things working. I copied and slightly modified one of your examples:

var BasicLayout = React.createClass({
  mixins: [React.PureRenderMixin],

  getDefaultProps: function() {
    return {
      className: "layout",
      items: 20,
      rowHeight: 30,
      cols: 12
    };
  },

  getInitialState: function() {
    var layout = this.generateLayout();
    return {
      layout: layout
    };
  },

  generateDOM: function() {
    return _.map(_.range(this.props.items), function(i) {
      return (<div key={i}><span className="text">{i}</span></div>);
    });
  },

  generateLayout: function() {
    var p = this.props;
    var layout = [];
    var y;
    for (i = 0; i <= p.items - 1; i++) {
      y = p['y'] || Math.ceil(Math.random() * 4) + 1;
      layout[i] = {x: i * 2 % 12, y: Math.floor(i / 6) * y, w: 2, h: y, i: i};
    }
    return layout;
  },

  onLayoutChange: function(layout) {
    this.props.onLayoutChange(layout);
  },

  render: function() {
    return (
      <ReactGridLayout layout={this.state.layout} onLayoutChange={this.onLayoutChange}
          {...this.props}>
        {this.generateDOM()}
      </ReactGridLayout>
    );
  }
});

Unfortunately, this triggers an error: TypeError: Cannot set property 'validated' of undefined. The relevant bit of code involves the line node._store.validated = true; within the following block:

function validateChildKeys(node, parentType) {
  if (Array.isArray(node)) {
    for (var i = 0; i < node.length; i++) {
      var child = node[i];
      if (ReactElement.isValidElement(child)) {
        validateExplicitKey(child, parentType);
      }
    }
  } else if (ReactElement.isValidElement(node)) {
    // This element was passed in a valid location.
    node._store.validated = true;
  } else if (node) {
    var iteratorFn = getIteratorFn(node);
    // Entry iterators provide implicit keys.
    if (iteratorFn) {
      if (iteratorFn !== node.entries) {
        var iterator = iteratorFn.call(node);
        var step;
        while (!(step = iterator.next()).done) {
          if (ReactElement.isValidElement(step.value)) {
            validateExplicitKey(step.value, parentType);
          }
        }
      }
    } else if (typeof node === 'object') {
      var fragment = ReactFragment.extractIfFragment(node);
      for (var key in fragment) {
        if (fragment.hasOwnProperty(key)) {
          validatePropertyKey(key, fragment[key], parentType);
        }
      }
    }
  }
}

I'm not sure how helpful that is on its own; I can get you the full trace if needed. For what it's worth, I'm using react-rails. The problem could lie within that, but I've tested some basic examples (not including RGL) and everything worked as expected.

Thanks!

column widths don't automatically adjust when scrollbar (dis)appears

Pretty much what the issue title is. Playing around with your demos, I noticed that when the scrollbar appears or disappears, the items don't autoadjust their size.

To repro what I'm talking about, open your basic demo and move things into the first column until the scrollbar appears (assuming you don't have it already). You should get an effect like this:
screenshot from 2015-03-16 14 15 20
If you then resize the window manually, they autoadjust the width and the effect goes away. If you then make the scrollbar disappear by moving things out of the first column, the reverse effect happens:
screenshot from 2015-03-16 14 19 24
For reference, this is what it should look like:
screenshot from 2015-03-16 14 18 51

The transform position dose not follow cursor immediately when dragging

Hi,
I included the "react-grid-layout.min.js" in my project(Rails v4.2 & React.JS v0.12.2). And I can use the ReactGridLayout Component without error, but it doesn't work as perfect as the demo on the github.
When i was dragging the item, the x,y in property "transform: translate(x,y);" doesn't change immediately with my cursor's position. It changed when the cursor dragged the item into another grid column.It seems the javascript dose not work as expected.

Floating grid items

Here is an image that will show the scenario that I describe. http://i.imgur.com/MHcoaCW.png

In the event that a large left side grid item exists and a large bar is brought to full width when attempting to drag an item it will only provide slots where the dragging item touches another grid item above it. However it'd be great to be able to drag to any available slot and not necessarily "float to the top".

I was just curious about the feasibility in implementing this or if this is something you see in this library?

Edit: After doing some digging I realized utils.compact is forcing this behavior. Seems like modifying the activeDrag to display anywhere, and also adding compact as a boolean is doable.
Also have to think about resizing and how that would be handled.

I guess a possible other idea would additionally be to "allowOverlap", however that seems more useful on a per-item basis, but not compacting and setting a specific layout that causes overlapping would theoretically work.

autosize with drag?

I can see that when you resize a widget the height of the container swells/contracts.

Is it possible to get this same functionality with dragging? Let's say I have a widget that I want to drag to the bottom of the screen for example?

Invalid checksum between server and client

I get this message:

React attempted to use reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server.

When using react-grid-layout to manage pages that are rendered on both the server and the client isomorphically. I can visually see that before client-side js loads, the layout looks different to after it loads. And when using .Responsive, it appears to be attempting to always use the smallest possible layout of all breakpoints specified.

When I remove the react-grid-layout component, there is no checksum error. Here is my component:

module.exports = React.createClass({
  displayName: 'Home',

  mixins: [Router.State],

  getLayout: function() {
    return {
      lg: [
        { x: 0, y: 0, w: 12, h: 3, i: 'home_heading' },
        { x: 0, y: 3, w: 12, h: 3, i: 'home_link' },
        { x: 3, y: 6, w: 6, h: 3, i: 'home_input' }
      ],
      md: [
        { x: 0, y: 0, w: 10, h: 3, i: 'home_heading' },
        { x: 0, y: 3, w: 10, h: 3, i: 'home_link' },
        { x: 2, y: 6, w: 6, h: 3, i: 'home_input' }
      ],
      sm: [
        { x: 0, y: 0, w: 8, h: 3, i: 'home_heading' },
        { x: 0, y: 3, w: 8, h: 3, i: 'home_link' },
        { x: 2, y: 6, w: 4, h: 3, i: 'home_input' }
      ],
      xs: [
        { x: 0, y: 0, w: 4, h: 3, i: 'home_heading' },
        { x: 0, y: 3, w: 4, h: 3, i: 'home_link' },
        { x: 1, y: 6, w: 2, h: 3, i: 'home_input' }
      ],
      xxs: [
        { x: 0, y: 0, w: 2, h: 3, i: 'home_heading' },
        { x: 0, y: 3, w: 2, h: 3, i: 'home_link' },
        { x: 0, y: 6, w: 2, h: 3, i: 'home_input' }
      ]
    };
  },

  devLayoutDebug: function(layout) {
    console.log(layout);
  },

  render: function() {
    return (
      <Title title="Home">
        <GridLayout
          breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
          cols={{ lg: 12, md: 10, sm: 8, xs: 4, xxs: 2 }}
          layouts={ this.getLayout() }
          rowHeight={ 40 }
          margin={ [0,0] }
          onLayoutChange={ this.devLayoutDebug }>
          <div style={ style.heading } key={ 'home_heading' }>Charity Profile</div>
          <div style={ style.outline } key={ 'home_link' }><Link to="profile" params={{ charitySlug: "Test Profile" }}>Profile</Link></div>
          <div style={ style.outline } key={ 'home_input' }><Input i18n={{ name: 'profile_test', label: 'Input Label' }} /></div>
        </GridLayout>
      </Title>
    );
  }
});

getOrGenerateLayout, getLayoutsFromSomewhere, example missing

I really like to use this, but there's one mayor issue with the docs.

The most essential part is left out, being the defining of the grid, and you're refering to fictional functions to generate layout. And the demo page is not showing really what exactly to give to layouts on the <ResponsiveReactGridLayout /> only some parsed coordinates, but not the actual format, which is expecting something like this:

 var layouts = {
    lg:[
      {h:2, w:2, x: 0, y: 0},
      {h:2, w:2, x: 1, y: 0},
      {h:2, w:2, x: 2, y: 0},
      {h:2, w:2, x: 3, y: 0}
    ],
    sm: [
      {h:2, w:2, x: 0, y: 0},
      {h:2, w:2, x: 1, y: 0},
      {h:2, w:2, x: 2, y: 0},
      {h:2, w:2, x: 3, y: 0}
    ],         
    md: [
      {h:2, w:2, x: 0, y: 0},
      {h:2, w:2, x: 1, y: 0},
      {h:2, w:2, x: 2, y: 0},
      {h:2, w:2, x: 3, y: 0}
    ],        
    xs: [
      {h:2, w:2, x: 0, y: 0},
      {h:2, w:2, x: 0, y: 1},
      {h:2, w:2, x: 0, y: 2},
      {h:2, w:2, x: 0, y: 3}
    ],
    xxs: [
      {h:2, w:2, x: 0, y: 0},
      {h:2, w:2, x: 0, y: 1},
      {h:2, w:2, x: 0, y: 2},
      {h:2, w:2, x: 0, y: 3}
    ]
  };

At least I THINK so, but there's not example anywhere to be found of what to give it, except somewhere in the source there's a method that generates some random numbers.

At least give an simple example of what to give to <ResponsiveReactGridLayout />

Are we supposed to guess what layout1 should look like in:

{lg: layout1, md: layout2, ...} 

max number of rows?

Is there a way to set a maximum number of rows?
Something like:

{ cols:4, maxRows: 10 }

Is something like this possible? Any pointers would be great!

Accessing isMounted inside its render()

The console gives me a warning that "ReactGridLayout is accessing isMounted inside its render()"
I know this doesn't affect the grid, but maybe in a later React version, this will become a real issue.

Only tested using React 0.13

Dragging should be optional

This looks cool - hope to use it to replace Masonry + JQuery. Don't want dragging behavior though, please allow passing a prop to turn it off.

Getting layout[i].x === NaN when onLayoutChange is called

Hi,

I copied your basic example, putting my own layout with draggable and resizable to true (super simple layout: 4x4 grid with width and height to 1). Everything render fine at the first run, but when I click on an item to drag it, onLayoutChange get called and the layout get mess up. I've noted that I receive NaN on the x value of the item I clicked on. If i ignore this, it will never happen again, but it's kind of glitchy.

Also, I never see the actual resize icon at the lower right corner, I'm I missing something in the CSS?, I've copied most of your example.

Thanks

Include dist in npm

Could the dist-dir be included in npm? I find it very handy to manage my dependencies with npm, but only plan on using the minified js.

Draggable ClientY is Null

I was trying to integrate your examples into a react webpack starter with routing. I added a new route, which I can get to show up as expected. However, on each drag event, I get the following error:

Uncaught TypeError: Cannot read property 'clientY' of nulldraggable.js:11
createUIEventdraggable.js:449 
module.exports.React.createClass.handleDragEnd

This occurs at draggable's:

function createUIEvent(draggable) {
    return {
        element: draggable.getDOMNode(),
        position: {
            top: draggable._pendingState.clientY,
            left: draggable._pendingState.clientX
        }
    };
}

PendingState is always null. It seems like a lifecycle issue, so i've tried a few different approaches, all with the same result (including using the example with no modifications).

Gist with files

Slow drag on svg element

Hi,

I've been using the grid-layout to display a grid of svg elements representing various metrics. Each grid element contain a button for options and the svg element which fill the remaining space. If I click and drag a grid element it can be fast or very slow. To drag if I click on my button it's fast and responsive, but when I click on my svg element it's suddenly very slow (even if my svg element is just an empty white rectangle of 300x300 pixels).

Any idea on what's causing the sudden drop in performance?

Thanks a lot!

accept function for maxH, maxW etc.

I need something a bit more complex for max dimensions of the resizable items than numbers. In my case the dimensions are not only globally restricted, but also by the current width/height of the item, i.e. an item with width 2 is allowed but only if the height is less than 3.
To cover these cases a function could be accepted as one of the max/min props, so that the restrictions can be calculated on the fly by checking the passed props (x, y). For now I solved it like this in GridItem.js, but this bypasses the proptype number validation.

maxH: function (props, propName, componentName) {
      if (typeof props.maxH !== 'function') {
        var _nr = props.maxH;
        props.maxH = function() { return _nr; };
      }
      React.PropTypes.func.apply(this, arguments);
...

This works for my particular case but breaks some validation and I'm wondering if this is the right way to solve this. Any suggestions would be nice!

Masonry-like layout

Hi guys, can someone provide me with an example of a masonry-like layout? I'm having a hard time getting things to work. In my case every item has a different height. So i don't get how to set the layout accordingly, because the examples provided only use multiples of a specific height...
At the moment i use:
<ResponsiveReactGridLayout className="layout" breakpoints={{lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0}} cols={{lg: 12, md: 10, sm: 6, xs: 4, xxs: 2}}>

This adjusts the width of my items perfectly. But as described above every container has the same height - i know how to set this height to another value, but i need a container the same height as my item.

Beside that all items are on the same position (stacked on each other).

An example or any help would be much appreciated,
thanks a lot!

Using it with bootstrap, the layout get messy

I try to setup this on top of a bootstrap 3 site, copy the css + sample css, and the grid render weirdly and the draggable handler get rendered out of place.

Any hint in how integrate it with bootstrap?

Dragging and resizing is not working on IE11

First thanks for the great library !

Currently dragging and resizing is not working in M$ IE11 (running on a Windows 7 VM). You can easily reproduce by trying to run the showcase demo in IE11 - https://strml.github.io/react-grid-layout/examples/0-showcase.html .

The problem seems to rely on react-draggable component and the way it detects if the device is a touch one. We found that by modifying draggable.js file (/node_modules/react-grid-layout/node_modules/react-draggable/lib/draggable.js) so that isTouchDevice is always false solve the problem.

So instead of having:

// @credits: http://stackoverflow.com/questions/4817029/whats-the-best-way-to-detect-a-touch-screen-device-using-javascript/4819886#4819886
/* Conditional to fix node server side rendering of component */
if (typeof window === 'undefined') {
    // Do Node Stuff
    var isTouchDevice = false;
} else {
    // Do Browser Stuff
    var isTouchDevice = 'ontouchstart' in window || // works on most browsers
      'onmsgesturechange' in window; // works on ie10 on ms surface
}

we do

var isTouchDevice = false;

the problem is fixed.

This seems to be a problem with touch detection in IE11 and probably must be fixed in react-draggable but just want to make sure people are aware of the problem and temporary solution. I will try to investigate the best solution and open an issue for react-draggable.

Can't build examples

When I npm run build-examples I get these errors:

I also had to change the name of the loader to babel in the webpack configs...

ERROR in ./test/examples/0-showcase.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/10-dynamic-min-max-wh.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/1-basic.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/2-no-dragging.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/3-messy.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/6-dynamic-add-remove.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/5-static-elements.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/7-localstorage.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/8-localstorage-responsive.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/4-grid-property.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

ERROR in ./test/examples/9-min-max-wh.jsx
Module build failed: ReferenceError: Unknown option: runtime
    at File.normalizeOptions (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:91:15)
    at new File (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/file.js:70:22)
    at Object.transform (/Users/ivan/dev/react-grid-layout/node_modules/babel-core/lib/babel/transformation/index.js:18:14)
    at transpile (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:54:24)
    at Object.module.exports (/Users/ivan/dev/react-grid-layout/node_modules/babel-loader/index.js:43:24)

Inconsistent dragging when using JSPM

I've spent an afternoon trying to resolve with no luck, was hoping someone could give some advice. I'm trying to use JSPM to install react-grid-layout, my basic installation looks like:

npm init
npm install jspm
jspm install react
jspm install jsx
jspm install npm:react-grid-layout

At this point I would expect react-grid-layout to work but jspm seems to load the react-resizable dependency incorrectly since it fails to load. To fix -

jspm install npm:react-resizable

At this point the console is clear, the grid is created with drag/resize functionality but dragging is inconsistent. The dragging grid item doesn't stay with the mouse and releasing the mouse doesn't "snap" the grid item into the correct position (it floats). I've tested multiple browsers, manually installing dependencies, compiling JSX > JS, tweaking CSS, etc.

children.map is not a function

For some reason I can't find a way to pass children into the grid.

I'm trying to do this:

<Grid className="layout" cols={12}>
    <div key={1} _grid={{x: 1, y: 0, w: 1, h: 2, static: true}} >
        {this.props.children}
    </div>
</Grid>

but I keep getting ReactGridLayout.js:85 Uncaught TypeError: children.map is not a function error.

Keeping the boxes within the limits of the container

I don't understand how the demo keeps the boxes within the container. In my own demo, they never want to stay in their container, even though their x and y values never dip below 0 or exceed the maximum w or h I set for them. Here is my code:

onLayoutChange(layout) {
  this.setState({layout: layout});
},

getInitialState() {
  var layout = [
    {i: 1, x: 0, y: 0, minW: 0, minH: 3, maxH: 12, w: 4, h: 3},
    {i: 2, x: 4, y: 0, minW: 0, minH: 3, maxH: 12, w: 4, h: 3},
    {i: 3, x: 8, y: 0, minW: 0, minH: 3, maxH: 12, w: 4, h: 3},
    {i: 4, x: 0, y: 1, minW: 0, minH: 3, maxH: 12, w: 12, h: 3}
  ]
  return {layout: layout};
},
render(){
  return <ReactGridLayout
    className="layout"
    rowHeight={30}
    isResizable={true}
    cols={12}
    layout={this.state.layout}
    onLayoutChange={this.onLayoutChange}
    >
    <div key={1}>1</div>
    <div key={2}>2</div>
    <div key={3}>3</div>
    <div key={4}>3</div>
  </ReactGridLayout>;
}

Dragging not working

Looks like another great React library! However, in the latest Chrome on OS X the dragging is not working, any idea why? If I try Packery or Gridster the dragging of items works as expected :)

Receive size from ReactGridLayout

I need to know what is real size of individual items so I can position them. Divs receive props.width and props.height, but they don't pass it to MyComponent.

    <ReactGridLayout className="layout" cols={12} rowHeight={30}>
      <div key={1} _grid={{x: 0, y: 0, w: 1: h: 2}}><MyComponent /></div>
      <div key={2} _grid={{x: 1, y: 0, w: 1: h: 2}}><MyComponent /></div>
      <div key={3} _grid={{x: 2, y: 0, w: 1: h: 2}}><MyComponent /></div>
    </ReactGridLayout>

So I tried to move MyComponent to top level like:

    <ReactGridLayout className="layout" cols={12} rowHeight={30}>
      <MyComponent key={1} _grid={{x: 0, y: 0, w: 1: h: 2}} />
      <MyComponent key={2} _grid={{x: 1, y: 0, w: 1: h: 2}} />
      <MyComponent key={3} _grid={{x: 2, y: 0, w: 1: h: 2}} />
    </ReactGridLayout>

But that does not work, because react-resizable access this.props.children.props.children. Which is undefined.

So I tried to replace the div with simple component which would pass the props to children:

var Item = React.createClass({
    render: function () {

        return React.addons.cloneWithProps(this.props.children)
    }
});

    <ReactGridLayout className="layout" cols={12} rowHeight={30}>
      <Item key={1} _grid={{x: 0, y: 0, w: 1: h: 2}}><MyComponent /></Item>
      <Item key={2} _grid={{x: 1, y: 0, w: 1: h: 2}}><MyComponent /></Item>
      <Item key={3} _grid={{x: 2, y: 0, w: 1: h: 2}}><MyComponent /></Item>
    </ReactGridLayout>

But after few renders, it goes wrong:

 Item.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object.

I suspect that React gets confused because react-resizable is changing this.children.props.children..

Hope my issue is clear.

Any idea how to get around it?

Breakpoints at or larger than the lg breakpoint don't save reliably

Go to https://strml.github.io/react-grid-layout/examples/8-localstorage-responsive.html

Resize or move a grid element, then make the window wider, then narrower, or narrower then wider. The layout will not have been saved most of the time (seems to only actually save about 20% of the time).

However, once the layout has been saved, it seems to work consistently from then on.

It seems that this issue isn't a problem when the page loads narrower than lg breakpoints.

draggable dependency is creating issues

The custom react-draggable fork referenced in package.json is causing issues with npm on winx86

npm http 304 http://registry.npmjs.org/react-draggable
npm WARN git config --get remote.origin.url returned wrong result
(git://github.com/strml/react-draggable)
npm http 304 http://registry.npmjs.org/react-resizable
npm WARN git config --get remote.origin.url returned wrong result
([email protected]:strml/react-draggable)
npm ERR! notarget No compatible version found: react-draggable@'strm
l/react-draggable'
npm ERR! notarget Valid install targets:
npm ERR! notarget ["0.1.0","0.1.1","0.2.0","0.2.1","0.3.0","0.4.0"]
npm ERR! notarget
npm ERR! notarget This is most likely not a problem with npm itself.

npm ERR! notarget In most cases you or one of your dependencies are
requesting
npm ERR! notarget a package version that doesn't exist.

npm ERR! System Windows_NT 6.1.7601
npm ERR! command "c:\Program Files (x86)\nodejs\node.exe" "c:\Pr
program Files (x86)\nodejs\node_modules\npm\bin\npm-cli.js" "inst
all" "react-grid-layout" "--save"
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.24
npm ERR! code ETARGET
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! not ok code 0

Bad performances on Firefox

I discovered your grid system a week ago and I was glad to see that it was clean and smooth, unlike the version I built for my project.

So today I was going to make myself a Christmas present by trying to fix my laggy version with your ideas. But as I refresh the github page, I see your new commit. And now we have the same problem. Try to replace your almost empty divs you use as items with more complex components, it's going to hurt, a lot.

I'm quite new to react, and so my suspicion after a WHILE trying to profile code execution, is that by cloning children for each rendering, it leads to re-render the whole set of items. And for my part, while dragging, I change a prop for the dragged item, which means calling render for every move event.

I didn't fully apprehended your new code as I write this, but I hope you already have a solution. :)
In the mean time I'm going to try with the zero child copy idea.

CSS Animations (with build script)

Opening a formal issue for the css issue I stumbled across here.

I did some digging, and discovered that the issue is introduced by replacing /react/lib/cloneWithProps/ with the react-clonewithprops library here. As you mentioned, we can't use /react/lib/cloneWithProps/, because it'll just trigger the issue in #40 again.

I poked around the source of react-clonewithprops and discovered this. My guess is that this is not exactly equivalent to the (now deprecated) cloneWithProps call. Facebook recommends using React.cloneElement instead, but I am having some trouble converting the two instances I found.

  1. In react-draggable
  2. In react-resizable

Any insight would be tremendously appreciated.

Thank you so much!

autoSize not working completely?

I'm having an issue with the autoSize flag. Each grid item seems to just take the h specified blindly regardless if this flag is set to true. The weird thing is that the resize handle is in the correct position as if it knows how tall the content is.
capture

Both of the grid items have an h of 1.

    getDefaultProps: function() {
        return {
            autoSize: true,
            isResizable: true,
            useCSSTransforms: true,
            draggableHandle: "div.draggable",
            cols: 12,
            rowHeight: 50
        };
    },
    render: function() {
       <ReactGridLayout className="layout" {...this.props}>
                <div key="test0">
                    <div className="draggable">TEST</div>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                </div>
                <div key="test1">
                    <div className="draggable">TEST</div>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                    <p>TESTTEST</p>
                </div>
       </ReactGridLayout>
    }

Am I doing something incorrectly?

this.props.onLayoutChange is not a function

Sorry if I'm doing something obviously wrong, I'm new to react and this component.

I used your example in 6-dynamic-add-remove.jsx. On line 73 (this.props.onLayoutChange) I get an error: "this.props.onLayoutChange is not a function.". If I comment the line out, I can use the code (but there are some issues with resizing). I render in a similar fashion to you:

document.addEventListener('DOMContentLoaded', function (event) {
var contentDiv = document.getElementById('content');
var gridProps = window.gridProps || {};
React.render(React.createElement(AddRemoveLayout, gridProps), contentDiv);
});

Differences: I'm not using your hooks, and I noticed that you are using a specific requires for "PureRenderMixin" whereas requiring React and using React.PureRenderMixin should also work?

You wouldn't happen to know if this is a common pitfall?

Add tests

The project is getting a little bit larger now, it needs a decent test suite at this point.

Bug with adding a new item to layout

I found a strange bug when adding a new item to layout. The new item is being positioned at a strange position, outside the layout. If I drag other items after the new is added, suddenly the new item goes to the right position.

After a brief investigation, I found out that for the new item, along with the standard CSS -xx-transform: translate(...) styles being added, a "top" and "left" are being added so that adds to the transform putting the new item in wrong position. You can see this behaviour happening in the example "dynamic add/remove" page as well.

This seems to be caused by the GridItem.js "mixinDraggable" function - there the useCSSTransforms property is false at first because this.isMounted() returns false. When some dragging occur, then it becames true as the element is already mounted.

So by changing the line inside function "mixinDraggable"

useCSSTransforms: this.props.useCSSTransforms && this.isMounted()

to

useCSSTransforms: this.props.useCSSTransforms

seems to fix the issue.

I was happy to submit a PR but I was wondering if not checking if the element isMounted could cause a regression somewhere else. What do you think ?

Reorganize elements after changing layout in props

Is there a way to have the grid move around elements to fit again if the layout is changed by other means than dragging?

For example, if I have two elements side by side:

leftright

and I change the w of the left one to span the maximum number of columns, right now the left element then overlaps the right element:

overlap

If the grid is remounted with the same exact layout, it recognizes this overlapping and properly moves down the right element under the left one:

fixed

Is there a way to do this without having to remount the grid?

Npm install fails from cloned repo (within an existing project)

Update: I've noticed the following happens only when required as a module in an existing project.

Noticed the NPM is out of date (does not include verticalCompact), so attempted to build from the repo itself...

> [email protected] install /Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook
> node bin/install

/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:138
    throw new Error('Unable to find a .git folder for this project');
          ^
Error: Unable to find a .git folder for this project
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:138:8)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
    at Object.exports.findGitRoot (/Users/Chad/react-grid-test/node_modules/react-grid-layout/node_modules/precommit-hook/node_modules/git-validate/lib/utils.js:135:24)
npm http 304 https://registry.npmjs.org/stable
npm ERR! [email protected] install: `node bin/install`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] install script.
npm ERR! This is most likely a problem with the precommit-hook package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     node bin/install
npm ERR! You can get their info via:
npm ERR!     npm owner ls precommit-hook
npm ERR! There is likely additional logging output above.

npm ERR! System Darwin 14.3.0
npm ERR! command "/usr/local/opt/nvm/v0.11.13/bin/node" "/usr/local/opt/nvm/v0.11.13/bin/npm" "i"
npm ERR! cwd /Users/Chad/react-grid-test/node_modules/react-grid-layout
npm ERR! node -v v0.11.13
npm ERR! npm -v 1.4.9
npm ERR! code ELIFECYCLE
npm http GET https://registry.npmjs.org/readable-stream
npm http 304 https://registry.npmjs.org/readable-stream
npm http GET https://registry.npmjs.org/core-util-is
npm http GET https://registry.npmjs.org/string_decoder
npm http 304 https://registry.npmjs.org/string_decoder
npm http 304 https://registry.npmjs.org/core-util-is
npm ERR! 
npm ERR! Additional logging details can be found in:
npm ERR!     /Users/Chad/react-grid-test/node_modules/react-grid-layout/npm-debug.log
npm ERR! not ok code 0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.