GithubHelp home page GithubHelp logo

dantrain / react-stonecutter Goto Github PK

View Code? Open in Web Editor NEW
1.2K 16.0 84.0 1.82 MB

Animated grid layout component for React

Home Page: http://dantrain.github.io/react-stonecutter

License: MIT License

JavaScript 100.00%
react react-component react-motion grid grid-component

react-stonecutter's Introduction

react-stonecutter npm version

Animated grid layout component for React, inspired by Masonry.
Choose between CSS Transitions or React-Motion for animation.

Demo

Installation

With npm:

npm install --save react-stonecutter

Usage

A simple layout with items of equal height:

import { SpringGrid } from 'react-stonecutter';
<SpringGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  itemHeight={200}
  springConfig={{ stiffness: 170, damping: 26 }}
>
  <li key="A">A</li>
  <li key="B">B</li>
  <li key="C">C</li>
</SpringGrid>

A Pinterest-style layout with varying item heights, this time using CSS transitions:

import { CSSGrid, layout } from 'react-stonecutter';
<CSSGrid
  component="ul"
  columns={5}
  columnWidth={150}
  gutterWidth={5}
  gutterHeight={5}
  layout={layout.pinterest}
  duration={800}
  easing="ease-out"
>
  <li key="A" itemHeight={150}>A</li>
  <li key="B" itemHeight={120}>B</li>
  <li key="C" itemHeight={170}>C</li>
</CSSGrid>

To render React components as children, wrap them in simple elements. This gives you full control of your markup:

<SpringGrid
  component="ul"
  // ...etc.
>
  {data.map((datum) => (
    <li key={datum.id}>
      <MyComponent datum={datum} />
    </li>
  ))}
</SpringGrid>

If you don't know the heights of your items ahead of time, use the measureItems higher-order component to measure them in the browser before layout:

import { SpringGrid, measureItems } from 'react-stonecutter';

const Grid = measureItems(SpringGrid);
<Grid
  // ...etc.
>
  <li key="A">Who controls the British crown?</li>
  <li key="B">Who keeps the metric system down?</li>
  <li key="C">We do!</li>
  <li key="D">We do!</li>
</Grid>

If your grid spans the page and you want to vary the number of columns based on the viewport width, use the makeResponsive higher-order component which makes use of enquire.js:

import { CSSGrid, measureItems, makeResponsive } from 'react-stonecutter';

const Grid = makeResponsive(measureItems(CSSGrid), {
  maxWidth: 1920,
  minPadding: 100
});

API Reference

Exports:

  • SpringGrid
  • CSSGrid
  • measureItems
  • makeResponsive
  • layout
  • enterExitStyle
  • easings

SpringGrid and CSSGrid props

columns={Number}
Number of columns. Required.
You can wrap the Grid component in the makeResponsive higher-order component to set this dynamically.

columnWidth={Number}
Width of a single column, by default in px units. Required.

gutterWidth={Number}
Width of space between columns. Default: 0.

gutterHeight={Number}
Height of vertical space between items. Default: 0.

component={String}
Change the HTML tagName of the Grid element, for example to 'ul' or 'ol' for a list. Default: 'div'.

layout={Function}
Use one of the included layouts, or create your own. Defaults to a 'simple' layout with items of fixed height.
Included layouts:

import { layout } from 'react-stonecutter';

const { simple, pinterest } = layout;

The function is passed two parameters; an Array of the props of each item, and the props of the Grid itself. It must return an object with this shape:

{
  positions: // an Array of [x, y] coordinate pairs like this: [[0, 0], [20, 0], [0, 30]]
  gridWidth: // width of the entire grid (Number)
  gridHeight: // height of the entire grid (Number)
}

Have a look at the code for the included layouts to get a feel for creating your own.

enter={Function}
entered={Function}
exit={Function}
These allow you to change how items animate as they appear and disappear from the grid. Supply functions that return objects with the opacity and transform values for an item's start and end states. By default the item's scale and opacity go from 0 to 1 and back to 0 on exit, like this:

enter={() => ({ scale: 0, opacity: 0 })}
entered={() => ({ scale: 1, opacity: 1 })}
exit={() => ({ scale: 0, opacity: 0 })}

The functions are passed three parameters, the item props, grid props and grid state which includes the current height and width of the grid. For example to have disappearing items fall off the bottom of the grid:

exit={(itemProps, gridProps, gridState) => ({ translateY: gridState.gridHeight + 500 })}

CSS transform-functions are split up so they can be easily animated individually. Supported functions:

  • translateX
  • translateY
  • translateZ
  • skew
  • skewX
  • skewY
  • scale
  • scaleX
  • scaleY
  • rotate
  • rotateX
  • rotateY

Some example functions are included:

import { enterExitStyle } from 'react-stonecutter';

const { enter, entered, exit } = enterExitStyle.foldUp;

Check out the demo to see them in action.

perspective={Number}
The perspective distance used for 3D transforms. If you are using a transform function like rotateX, use this to strengthen the effect. Default is no perspective applied.

lengthUnit={String}
The length unit used throughout. Default: 'px'. Experimental. You could try using 'em' or 'rem' and then adjust the font-size for a fluid layout, but it may not work well with the measureItems and makeResponsive higher-order components. % does not work well due to the way CSS transforms work.

angleUnit={String}
The angle unit. Affects transform-functions such as rotate. Default: 'deg'.

SpringGrid only props

springConfig={Object}
Configuration of the React-Motion spring. See the React-Motion docs for more info. Default: { stiffness: 60, damping: 14, precision: 0.1 }.

CSSGrid only props

duration={Number}
Animation duration in ms. Required.

easing={String}
Animation easing function in CSS transition-timing-function format. Some Penner easings are included for convenience:

import { easings } from 'react-stonecutter';

const { quadIn, quadOut, /* ..etc. */  } = easings;

Default: easings.cubicOut.

measureItems options

Pass like this:

const Grid = measureItems(SpringGrid, { measureImages: true })

measureImages: Boolean
If set to true, waits for images to load before measuring items and adding them to the Grid. This may be necessary if you don't know the height of your images ahead of time. Powered by imagesLoaded.

background: Boolean|String
This option is passed through to the imagesLoaded library. It allows you to wait for background images to load, in addition to <img> tags.

makeResponsive options

Pass like this:

const Grid = makeResponsive(SpringGrid, { maxWidth: 1920 })

maxWidth: Number
Maximum width for the Grid in px.

minPadding: Number
Minimum horizontal length between the edge of the Grid and the edge of the viewport in px. Default: 0.

defaultColumns: Number
Default number of columns before the breakpoints kick in. May be useful when rendering server-side in a universal app. Default: 4.

Alternatives

If you have a list already nicely laid out by the browser, check out React Flip Move which uses the very cool FLIP technique.

License

MIT

react-stonecutter's People

Contributors

aaronccwong avatar dantrain avatar stormslowly 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

react-stonecutter's Issues

Images are overlapped.

Hi ,

I don't know the heights of my items ahead of time and try to use the measureItems higher-order component to measure them in the browser before layout using the following snippet.

import { SpringGrid, measureItems } from 'react-stonecutter';

const Grid = measureItems(SpringGrid);
<Grid
component="ul"
columns={3}
columnWidth={350}
gutterWidth={3}
gutterHeight={3}
layout={layout.pinterest}

  • IMG A
  • IMG B
  • IMG C
  • IMG D
  • But I am getting all images are overlapped with the single image. Any idea about this issue. I want to implement "Pinterest grid layout".

    image

    Issue with pagination

    Hello, I want to say that your component is really awesome, I modified the measureItems file, order to wait for the load of image in individual children.

    But I have a problem with pagination, the first time the page only flash, it's because you use a grid when the elements are not new and size was calculated, so, Can I render in a grid the new and the old elements?

    (I'm sorry for my very bad english, I'm not a native speaker).

    Thank you and best regards.

    Server-side rendering

    Hi,

    I'm using react-stonecutter on a server-side rendered page. You can see the example here: https://smartariffa.it/.

    The server-side rendering is working, you can see that the cards content is present in the html source, search for โ€œSenza limitiโ€ for instance. However when the page loads the cards aren't displayed, until the Stonecutter layout calculation is done (I'm using measureItems with a custom layout and a SpringGrid) โ€” which takes about 1 sec in the above example.

    Do you have any idea why stonecutter โ€œre-hydratingโ€ isn't working as for other React server-side rendered components, and do you have any pointer about how to fix this issue?

    Accept non-px columnWidth value.

    Since the column width is a fixed value, is there a way to specify it in % or "vw", instead of "px"?

    I can't seem to get how can I achieve responsive column widths.

    Thanks!

    request: accommodate file imports

    I found that by targeting specific Stonecutter source files in my imports, I saved around 220 KB in my (webpack) bundle -- a little more than 80% (pre-minified) compared to importing without direct paths. Everything still functions perfectly:

    // before
    import { CSSGrid, layout, easings } from 'react-stonecutter';
    
    // after
    import CSSGrid from 'react-stonecutter/src/components/CSSGrid';
    import simple from 'react-stonecutter/src/layouts/simple';
    import { expoOut } from 'react-stonecutter/src/utils/easings';
    

    To do this, though, I had to reconfigure webpack for .jsx files, add the /src path for compilation, and enable a few Babel loaders that I wasn't already using.

    It would be great if the /lib directory could also include compiled versions of the modules in /src. You can see an example of this in the Redux source; see /src/applyMiddleware.js compared to /lib/applyMiddleware.js.

    I would contribute this myself but am unfamiliar with the Gulp/Weback build config you're using. Otherwise I'm happy to pitch in where possible if you think this is worthwhile.

    allow any element

    Currently, if you provide custom react components under <CSSGrid>, it will throw an error.
    The code is here https://github.com/dantrain/react-stonecutter/blob/master/src/utils/assertIsElement.js

    The solution is to wrap it with an extra <div>. Unfortunately, it doesn't work well for me because I also use react-dnd, and I have a weird bug on mobile.

    Is possible to remove this validation? I am using a fork with this change and it works without any problems.
    The custom component must only apply provided style to the main <div>.

    Randomize/shuffle childred

    Hey, in the live demo there is a button to randomize children. How is that implemented? Can you please let me know?

    Unknown prop `minPadding`

    I get a warning when I use the Grid component.

    This is my code:

    <Grid component="ul"
        columns={5}
        columnWidth={150}
        gutterWidth={5}
        gutterHeight={5}
        duration={800}
        easing="ease-out">
            <li key="A">Who controls the British crown?</li>
            <li key="B">Who keeps the metric system down?</li>
            <li key="C">We do!</li>
            <li key="D">We do!</li>
    </Grid>
    

    This is what I get in the console:

    Warning: Unknown prop minPadding on

      tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
      in ul (created by ReactTransitionGroup)
      in ReactTransitionGroup (created by CSSGrid)
      in CSSGrid (created by Constructor)

    React does not recognize the `itemHeight` prop on a DOM element

    Hi when adding itemHeight to an li to a css grid like the example I get the message React does not recognize the itemHeight prop on a DOM element. When I remove the prop I get a warning Uncaught Error: Each child must have an "itemHeight" prop or an "itemRect.height" prop. How can I work around this?

    measureItems causes entire tree to be re-rendered

    I'm creating my grid like this:

    private render() {
          const Grid = makeResponsive(measureItems(SpringGrid), { maxWidth: 1024, minPadding: 50, defaultColumns: 2 });
          let children = this.props.items.map(i =><li key={i.Id}><ItemCard item={i}  /></li>);
            
          return <div className='items-panel'>
              <Grid component='ul' columnWidth={300} gutterWidth={10} gutterHeight={10} layout={layout.pinterest}>
                        {children}
              </Grid>
          </div>;
    }

    When I pass in only one item as my items, I'm seeing ItemsCard's constructor being called twice:
    Once as a result of being in the elementsToMeasure collection, and then again after a state change when the element has been measured. On that second pass 'cloneElement' adds the itemRect property to the object props, and as a result, the initial object is torn down and removed from the DOM and the new item is added.

    Is there any way to make this more efficient so that it doesn't recalcuate, as my ItemCard is quite a large component.

    Is there some optimization I need to do in my ItemCard? I attempted to add the lifecycle events for componentWillReceiveProps but it is never called due to cloning.

    Animate single grid item

    If there is only one item in the grid, exit animation doesn't work because grid instantly unmounts (I am talking about SpringGrid). Same for entering animation, SpringGrid doesn't exist when first item enters.

    I wonder if i'm doing something wrong, but it looks like a bug to me. Also, great work on this component!

    Internal Library errors, due to dependancies allowing React 15.4

    React 15.4 changes the internals of react, and react-dom. For both of these dependancies, react-stonecutter uses ^15.3.2 instead of ~15.3.2.

    Using ^ allows npm to skip up to the latest minor version, thus using react 15.4.0. If this dependency changed to ~, stonecutter would stop at 15.3.N, where N is the last published version of 15.3.

    (I'd love just make a pull request for what's basically a one-character change, but sadly I'm on a company-owned machine right now with all kinds of restrictions on open source stuff)

    Pinterest-Like when height unknown

    I am attemptiong to render a Pinterest-type board, but am receiving the following error;
    Error: Each child must have an "itemHeight" prop or an "itemRect.height" prop.

    I will be rendering Semantic UI Card components with various headers and images, so I do not know the size of the rendered components.

    I have demonstrated this below with cats instead of cards;

    import React, { Component } from 'react';
    import { CSSGrid, layout, measureItems } from 'react-stonecutter';
    import uuid from 'uuid';
    
    const Grid = measureItems(CSSGrid);
    
    export default class extends Component {
      render() {
        return (
          <CSSGrid
            component="ul"
            columns={5}
            columnWidth={290}
            gutterWidth={5}
            gutterHeight={5}
            layout={layout.pinterest}
            duration={800}
            easing="ease-out"
          >
          <div id="cats">
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
            <img width={290} src={"http://thecatapi.com/api/images/get?format=src&type=jpg&rnd=" + uuid.v4() } />
          </div>
          </CSSGrid>
        )
      }
    }

    Failed to render responsive grid correctly when the width is not 100%.

    Just realised that you use enquire.js which sets the media queries to achieve the responsive view. This works fine when the grid occupies 100% in width. However, when the page comes with a side navigation, the grid will be wider than it's parent container.

    Do you have any workaround for this? Or I have to write my own makeResponsive HoC?

    window not defined error

    If I include this module in my react project I get window undefined error thrown related to enquire.js library.

    Not isomorphic friendly

    First I must say this is a great package! Easy to use (i actually find the Grid example component easier so I'm using that one).

    I'm using React Starter Kit - www.reactstarterkit.com, isomorphic is great coz it allows my user to see content without any javascript being downloaded. But looks like this library isn't isomorphic friendly. Layout isn't calculated when I render from the server side, therefore even though my content is sent down on the initial load, but no UI is shown.

    I'm not using responsive, so it should be doable to do layout on the sever side. Tried to do some debugging but can't find how to solve it. Any suggestions?

    Cards collapse all in one piled up deck

    I have used this tool and it works awesome(great job) but I am facing a problem when minimizing the browser window width below 480px using my mouse or opening the application on a smartphone.
    Every card is collapsing into each other for all rows and columns and forming like a piled up deck of cards.

    I am using the div as a tag and I created my card using bootstrap grid base system (e.g: col-xs-12 col-sm-12 col-md-12 col-lg-12)

    ===========================

    let Catalogue = measureItems(SpringGrid,{ measureImages: true , background:true });
    Catalogue = makeResponsive(Catalogue, {
                  maxWidth: 1900,
                  minPadding: 80,
                  defaultColumns: 4
                });
    
    const CardCatalogue = ({dataItems}) => {
    
      const setupGrid = {
            layout:layouts.pinterest,//simple, pinterest
            widthColumn:400,
            itemsHeight:530,
            stiffness:250,
            damping:15,
            perspectiveAmt:600,
            guttersWidth:10,
            guttersHeight:10,
            columns:3,
            duration:800
          };
    
      return(
        <Catalogue
          component='div' 
          columnWidth={setupGrid.widthColumn} 
          gutterWidth={setupGrid.guttersWidth} 
          gutterHeight={setupGrid.guttersHeight} 
          layout={setupGrid.layout}
          springConfig={{ stiffness: setupGrid.stiffness, damping: setupGrid.damping }}
          perspective={setupGrid.perspectiveAmt}
          duration={setupGrid.duration}>
        {
          dataItems.map((item) => (
            <div className='card2 tariffCardWidth400px card-1 row noPadMar borderThicker' key={item.id}> <ItemCard  key={item.id} item={item} /></div>
          ))
        }
        </Catalogue>
      );
    };
    
    CardCatalogue.propTypes = {
      dataItems: PropTypes.array.isRequired
    };
    
    export default CardCatalogue;
    

    =========================================

    From what I am seeing in the html source code in chrome the transform style is going from (for 2 items)
    item1: position: absolute; top: 0px; left: 0px; z-index: 2; opacity: 1; transform: translateX(0px) translateY(0px) perspective(600px) scale(1);
    item2: position: absolute; top: 0px; left: 0px; z-index: 2; opacity: 1; transform: translateX(0px) translateY(553px) perspective(600px) scale(1);

    into for both of the items
    position: absolute; top: 0px; left: 0px; z-index: 2; opacity: 1; transform: translateX(-410px) translateY(0px) perspective(600px) scale(1);

    Its weird because -410 is the width for each item 400+10(gutter).

    Am I doing something wrong?

    =================================================

    css that i use on the div inside the map is

    .tariffCardWidth400px{
      width: 400px;
    }
    
    .card2 {
      background: #ffffff;
      border-radius: 1px;
      display: inline-block;
      position: relative;
      overflow-y: auto;
      padding: 0;
      margin: 0;
    border-bottom-width: 40px!important;
      border-bottom-color: #49C5D1!important;
    }
    
    .card-1 {
      box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
      transition: all 0.3s cubic-bezier(.25,.8,.25,1);
    }
    
    .card-1:hover {
      box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
    }
    
    .noPadMar{
      padding-left: 0px!important;
      padding-right: 0px!important;
      padding-top: 0px!important;
      padding-bottom: 0px!important;
    
      margin-left: 0px!important;
      margin-right: 0px!important;
      margin-top: 0px!important;
      margin-bottom: 0px!important;
    }
    
    .borderThicker{
      border-color: #e7eaec;
      border-width: thin;
      border-style: solid;
    }
    

    React 15+

    You have done a great job with this component! Any plans to support React 15 and above? Thank you.

    React components as Grid children

    Looks like it expects DOM elements only and when React components supplied as children, there is an error shown KeyEscapeUtils.js?ac04:28 Uncaught RangeError: Maximum call stack size exceeded

    centered layout?

    Is there a layout that will center items when the row is not full?

    when add item too frequent, layout got exception

    image

    the reason is that when imagesloaded callback is called, the DOM still don't have height (0).
    so when layout try to layout the item it throws the error.

    my current solution is using lodash debounce to slow down the speed of add items.

    i will fix it by check the height element when imagesloaded

    Uncaught Error: Each child must have an "itemHeight" prop or an "itemRect.height" prop.(anonymous function) @ react-stonecutter.js:1298t.default @ react-stonecutter.js:1292t.default.u.default.createClass.doLayout @ react-stonecutter.js:403CSSGrid_componentWillReceiveProps @ react-stonecutter.js:399O.updateComponent @ ReactCompositeComponent.js:601O.receiveComponent @ ReactCompositeComponent.js:534s.receiveComponent @ ReactReconciler.js:131l.updateChildren @ ReactChildReconciler.js:94D.Mixin._reconcilerUpdateChildren @ ReactMultiChild.js:213D.Mixin._updateChildren @ ReactMultiChild.js:315D.Mixin.updateChildren @ ReactMultiChild.js:303v.Mixin._updateDOMChildren @ ReactDOMComponent.js:938v.Mixin.updateComponent @ ReactDOMComponent.js:767v.Mixin.receiveComponent @ ReactDOMComponent.js:723s.receiveComponent @ ReactReconciler.js:131O._updateRenderedComponent @ ReactCompositeComponent.js:737O._performComponentUpdate @ ReactCompositeComponent.js:715O.updateComponent @ ReactCompositeComponent.js:634O.performUpdateIfNecessary @ ReactCompositeComponent.js:548s.performUpdateIfNecessary @ ReactReconciler.js:165u @ ReactUpdates.js:151i.perform @ Transaction.js:138i.perform @ Transaction.js:138p.perform @ ReactUpdates.js:90T @ ReactUpdates.js:173i.closeAll @ Transaction.js:204i.perform @ Transaction.js:151d.batchedUpdates @ ReactDefaultBatchingStrategy.js:63s @ ReactUpdates.js:201o @ ReactUpdateQueue.js:25f.enqueueSetState @ ReactUpdateQueue.js:209o.setState @ ReactComponent.js:64u.default.createClass.updateRects @ react-stonecutter.js:1208r @ index.js:149d @ index.js:196p @ index.js:184
    
    

    Help implementing custom layout

    I've found myself with the following situation:

    • Items placed using pinterest layout are properly arranged. No overlapping, gutters correctly place and distributed
    • Items got an image and text
    • simple layout would just overlap / smash every item
    • I don't particularly need ร  la pinterest layout but every column starting a a common height

    I tried to pass a custom layout overwriting the pinterest layout code.

    I've got this:

    import { chunk } from "lodash";
    
    export default function(items, props) {
      const { columns, columnWidth, gutterWidth, gutterHeight } = props;
    
      const columnHeights = [];
      for (let i = 0; i < columns; i++) {
        columnHeights.push(0);
      }
    
      const positions = items.map(itemProps => {
        const column = columnHeights.indexOf(Math.min.apply(null, columnHeights));
    
        const height =
          itemProps.itemHeight || (itemProps.itemRect && itemProps.itemRect.height);
    
        if (!(height && typeof height === "number")) {
          throw new Error(
            'Each child must have an "itemHeight" prop or an "itemRect.height" prop.'
          );
        }
    
        const x = column * columnWidth + column * gutterWidth;
        const y = columnHeights[column];
    
        columnHeights[column] += Math.round(height) + gutterHeight;
    
        return [x, y];
      });
    
      const allHeights = items.map(itemProps => 
        itemProps.itemHeight || (itemProps.itemRect && itemProps.itemRect.height)
      );
    
      const chunkHeights = chunk(allHeights, columns);
    
      const gridWidth = columns * columnWidth + (columns - 1) * gutterWidth;
      const gridHeight = Math.max.apply(null, columnHeights);
    
      const rows = chunk(positions, columns);
      let previewRowYStart = 0;
      let previewRowYEnd = 0;
      const orderedPositions = rows.map((row: any, rowIndex) => {
        const columnsYPositions = row.map(([x, y]) => y);
        const max = Math.max(...columnsYPositions);
        let yPosition = max;
        if (rowIndex !== 0) {
          const overlap = previewRowYEnd >= max;
          if (overlap) yPosition = (max + (previewRowYEnd - max)) * 1.05;
        }
    
        previewRowYStart = rowIndex === 0 ? 0 : max;
        previewRowYEnd = max + Math.max(...chunkHeights[rowIndex] as number[]);
    
        return row.map(([ x ]) => [ x, yPosition ]);
      });
    
      return { positions: orderedPositions.flat(1), gridWidth, gridHeight };
    }

    Where basically I'm trying to order the item Y position into chunks according to their row, take the highest and set a common Y for all of them. Also I'd take previous row height and detect the chance of an overlap, adding some extra distance if overlapping.

    This seems to work except that in some cases, the distance between rows is huge. I've tried to adjust the yPosition calculation when there's an overlap and also reduced the gutter but I can't get a consistent and logic result.

    Any suggestions or directions would be appreciated

    Changing columnWidth prop doesn't cause rerender to UI

    I have a grid layout that recalculates the size of my grid items to take up the remaining space. Currently the CSSGrid component renders this correctly on the first render but when the columnWidth prop changes the grid does not update to respect this. Is there a way to get this to work or is it a limitation of stonecutter?

    Thanks.

    Drag & Drop reorder

    Any plans to implement Drag & Drop reorder of panels? That would be a killing feature!

    React 15.2 Unknown props

    With React 15.2+ I'm seeing the unknown props warning in react-stonecutter:

    Warning: Unknown props columnWidth, gutterWidth, gutterHeight, minPadding, columns, angleUnit, layout, enter, entered, exit on

    tag. Remove these props from the element. For details, see https://fb.me/react-unknown-prop

    and

    Warning: Unknown prop itemRect on

    tag. Remove this prop from the element.

    Not sure what FB changed but lots of libs are tossing these warnings now. Stonecutter still works, but just wanted to give you a heads up.

    How to move elements location?

    I am using this control, but I want to move a tile to the bottom if it doesn't have an image associated with it. Is there a way to move a tile programatically?
    Also, do tiles support resizing and drag and drop?

    First element disapear

    Hi,

    I have an issue with react-stonecutter because the first element of my list disappear when the screen is lower that 400px. It add a <!-- react-empty: 2967 --> instead.

    See below which parameters of react-stonecutter I use.

    const Grid = makeResponsive(measureItems(CSSGrid, { measureImages: true }), {
      maxWidth: 1920,
      minPadding: 100
    });
    
            <Grid
                component="ul"
                columns={5}
                columnWidth={300}
                gutterWidth={10}
                gutterHeight={8}
                layout={layout.pinterest}
                duration={800}
                easing="ease-out"
                className="cards list_styled-none"
              >
                {ids.map((id, key) => (
                  <li key={key} className={roles[id].children.length > 0 ? "card_container card" : "card"}>
                    <Card role={roles[id]}/>
                  </li>
                ))}
              </Grid>
    

    Thanks for you help!

    Overlapping items when height changes

    Here is how it looks like. I think the reason is that the item changes size after the grid is created. I don't know how to fix this. Tried measureImages but wont work. Any help? thanks

    image

    image

    IE11 bug

    Number.isNaN is not supported in IE causing components that import this to break.

    Sorting option for SpringGrid

    react-stonecutter is an amazing package, many thanks. In addition, I thought it would have been great if it had sorting option for SpringGrid. Currently it works as per the masonry but compromises with the order (well, nothing wrong in it).

    sorted

    Unable to get the responsive design without specifying the height(itemHeight) in Grid and child component

    Hi,
    we are not able to get the responsive design while adding the data dynamically in to the box of GRID. we are not knowing the height of the box and dynamically it will change. so Can you please help me solve the issue?

    const Grid = measureItems(SpringGrid);
    <Grid component="div" columnWidth={257} gutterWidth={5} columns={3} gutterHeight={5} layout={layout.pinterest} duration={800} easing="ease-out" measured={true}>
    					{	
    						this.state.selectedFilter.map(function(compObj, idx){
    							return(
    								<div className="grid-item"  key={compObj.compName} style={{width: 257,height:'auto'}}>
    									<FilterInfoBox filterObj={compObj} filterRemoveFn={_this.toggleFilter}/>
    								</div>)
    						})
    					}
    </Grid>
    

    Can't install sass if react-stonecutter is installed

    I have a Next app with react-stonecutter installed. But when I try to install sass, react-motion gets deleted. Or, if I install react-motion, sass gets deleted.
    I got:

        "react-motion": "^0.5.2",
        "react-scripts": "^5.0.1",
        "react-stonecutter": "^0.3.10"
    

    Stuck in single-column layout

    A part of my project is a layout of cards similar to the react-stonecutter example. I've tried to implement stonecutter into my cards area, but my cards render in a single column (vice a proper responsive layout).

    My assumption is I'm missing some obvious setting, but I can't quite figure it out. Is there a simple reason this might be happening?

    All the components involved here are either direct from Material-UI or slightly modified versions (e.g., <ListingCard> == <Card>++).

    The data structures are Immutable.js, so the methods I'm using (map, filter) aren't native JS, if that matters.

    import React from 'react'
    import ListingCard from 'components/ListingCard'
    import SelectField from 'material-ui/SelectField'
    import { SpringGrid, makeResponsive } from 'react-stonecutter';
    
    const Grid = makeResponsive(SpringGrid, { maxWidth: 1020, minPadding: 100, defaultColumns: 4 })
    
    export class ListingsArea extends React.Component {
    
      render() {
        return (
          <div style={style.wrapper}>
            <div style={style.controlRow}>
              <SelectField
                floatingLabelText="Sorted by..."
                >
                {items}
              </SelectField>
    
            </div>
            <Grid
              columnWidth={300}
              gutterWidth={5}
              gutterHeight={5}
              itemHeight={500}
              springConfig={{ stiffness: 170, damping: 26 }}
              >
    
              {
                this.props.userListings
                  .filter(/*filter code*/)
                  .map((val, key) => {
                    return <ListingCard data={val}/>
                  })
              }
            </Grid>
          </div>
        )
      }
    }
    
    
    const style = {
      wrapper: {
        marginLeft: '25px',
      },
      controlRow: {
        width: '100%',
      }
    }
    

    Uncaught Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs.

    I want to use react-stonecutter with my existing project. However when I tried the simple usage example, nothing is displayed from the <CSSGrid/>. All I am getting is this error:

    Uncaught Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. You might be adding a ref to a component that was not created inside a component's render method, or you have multiple copies of React loaded (details: https://fb.me/react-refs-must-have-owner).

    import React from 'react'
    
    import { CSSGrid, layout } from 'react-stonecutter';
    
    export default class Photos extends React.Component {
        render() {
            return(
                <div id="profile_photos">
                   <div id="profile_photos_nav">
                       <span class="photo_nav" id="photo_timeline">
                           <button class="active_btn">Timeline Photos</button>
                        </span>
                       <span class="photo_nav" id="photo_profile">
                           <button>Profile Photos</button>
                       </span>
                       <span class="clear_both"></span>
                   </div>
    
                   <CSSGrid
                      component="ul"
                      columns={5}
                      columnWidth={150}
                      gutterWidth={5}
                      gutterHeight={5}
                      layout={layout.pinterest}
                      duration={800}
                      easing="ease-out"
                    >
                      <li key="A" itemHeight={150}>A</li>
                      <li key="B" itemHeight={120}>B</li>
                      <li key="C" itemHeight={170}>C</li>
                    </CSSGrid>
    
                </div>
            );
        }
    }
    

    I don't know whether this is relevant, but I am using "react": "^15.1.0", and while installing this package, I got this warning:

    npm WARN peerDependencies The peer dependency react@^15.2.0 included from react-addons-transition-group will no
    npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
    npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
    

    Can you please help me with this? Thank you.

    Fit to parent

    I am wondering if its possible to make the grid fit to the width of the parent, instead of defining a maxWidth via makeResponsive.

    I am using the SprintGrid to render items within a parent div. It seem as though the component always has a fixed width that I can't control unless I specify the full width on init.

    Any ideas?
    Kai

    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.