Skip to content

Commit

Permalink
Refactor with Flow and fix all type errors.
Browse files Browse the repository at this point in the history
  • Loading branch information
STRML committed Nov 23, 2015
1 parent 0f92424 commit 5984775
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 28 deletions.
5 changes: 5 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,10 @@
},
"ecmaFeatures": {
"jsx": true
},
"globals": {
// For Flow
"ReactElement",
"ReactClass"
}
}
6 changes: 6 additions & 0 deletions .validate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"scripts": {
"lint": "jshint ."
},
"pre-commit": ["lint", "validate", "test"]
}
4 changes: 1 addition & 3 deletions lib/GridItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {Resizable} from 'react-resizable';
import assign from 'object-assign';

import type {Position, Size} from './utils';
/*global ReactElement*/

/**
* An individual item within a ReactGridLayout.
Expand Down Expand Up @@ -169,8 +168,7 @@ export default class GridItem extends Component {

// This is used for server rendering.
if (this.props.usePercentages) {
pos.left = perc(pos.left / this.props.containerWidth);
style.left = pos.left;
style.left = perc(pos.left / this.props.containerWidth);
style.width = perc(pos.width / this.props.containerWidth);
}

Expand Down
12 changes: 9 additions & 3 deletions lib/ReactGridLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import GridItem from './GridItem';
// import WidthListeningMixin from './mixins/WidthListeningMixin';

// Types
/*global ReactElement*/
import type {Layout, LayoutItem, ResizeEvent, DragEvent} from './utils';
type State = {
activeDrag: ?LayoutItem,
Expand Down Expand Up @@ -205,6 +204,7 @@ export default class ReactGridLayout extends React.Component {
onDragStart(i: number, x: number, y: number, {e, element}: DragEvent) {
var layout = this.state.layout;
var l = getLayoutItem(layout, i);
if (!l) return;

this.setState({oldDragItem: clone(l)});

Expand All @@ -222,6 +222,7 @@ export default class ReactGridLayout extends React.Component {
onDrag(i: number, x: number, y: number, {e, element}: DragEvent) {
var layout = this.state.layout;
var l = getLayoutItem(layout, i);
if (!l) return;
var oldL = this.state.oldDragItem;

// Create placeholder (display only)
Expand Down Expand Up @@ -254,6 +255,7 @@ export default class ReactGridLayout extends React.Component {
onDragStop(i: number, x: number, y: number, {e, element}: DragEvent) {
var layout = this.state.layout;
var l = getLayoutItem(layout, i);
if (!l) return;
var oldL = this.state.oldDragItem;

// Move the element here
Expand All @@ -272,6 +274,7 @@ export default class ReactGridLayout extends React.Component {
onResizeStart(i: number, w: number, h: number, {e, element}: ResizeEvent) {
var layout = this.state.layout;
var l = getLayoutItem(layout, i);
if (!l) return;

this.setState({oldResizeItem: clone(l)});

Expand All @@ -281,6 +284,7 @@ export default class ReactGridLayout extends React.Component {
onResize(i: number, w: number, h: number, {e, element}: ResizeEvent) {
var layout = this.state.layout;
var l = getLayoutItem(layout, i);
if (!l) return;
var oldL = this.state.oldResizeItem;

// Set new width and height.
Expand Down Expand Up @@ -348,9 +352,11 @@ export default class ReactGridLayout extends React.Component {
* @param {Number} i Index of element.
* @return {Element} Element wrapped in draggable and properly placed.
*/
processGridItem(child: ReactElement): ReactElement {
var i = child.key;
processGridItem(child: ReactElement): ?ReactElement {
if (!child.key) return;
var i = parseInt(child.key, 10);
var l = getLayoutItem(this.state.layout, i);
if (!l) return;

// watchStart property tells Draggable to react to changes in the start param
// Must be turned off on the item we're dragging as the changes in `activeDrag` cause rerenders
Expand Down
5 changes: 2 additions & 3 deletions lib/ResponsiveReactGridLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ import ReactGridLayout from './ReactGridLayout';
// import WidthListeningMixin from './mixins/WidthListeningMixin';

// Types
/*global ReactElement*/
import type {Layout} from './utils';
type ResponsiveLayout = {lg?: Layout, md?: Layout, sm?: Layout, xs?: Layout, xxs?: Layout};
import type {ResponsiveLayout} from './responsiveUtils';
type State = {
layout: Layout,
layouts: ResponsiveLayout,
breakpoint: string,
cols: number,
width: number
}
};
// End Types

/**
Expand Down
52 changes: 52 additions & 0 deletions lib/components/ListensToWidth.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// @flow
import { PropTypes, Component } from 'react';
import ReactDOM from 'react-dom';

type Props = {initialWidth: number, listenToWindowResize: boolean};

/**
* A simple HOC that provides facility for listening to container resizes.
*/
export default (ComposedComponent: ReactClass): ReactClass => {
return class extends Component {
static propTypes = {
// This allows setting this on the server side
initialWidth: PropTypes.number,

// If false, you should supply width yourself. Good if you want to debounce resize events
// or reuse a handler from somewhere else.
listenToWindowResize: PropTypes.bool
};

static defaultProps: Props = {
initialWidth: 1280,
listenToWindowResize: true
};

componentDidMount() {
if (this.props.listenToWindowResize) {
window.addEventListener('resize', this.onWindowResize);
// This is intentional. Once to properly set the breakpoint and resize the elements,
// and again to compensate for any scrollbar that appeared because of the first step.
this.onWindowResize();
this.onWindowResize();
}
}

componentWillUnmount() {
window.removeEventListener('resize', this.onWindowResize);
}

/**
* On window resize, update width of child by calling listener directly.
* TODO: cleaner way to do this?
*/
onWindowResize = () => {
this.refs.child.onWidthChange(ReactDOM.findDOMNode(this).offsetWidth);
};

render(): ReactElement {
return <ComposedComponent {...this.props} ref="child" />;
}
};
};
10 changes: 5 additions & 5 deletions lib/responsiveUtils.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// @flow

import utils from './utils';
import {compact, correctBounds} from './utils';

import type {Layout} from './utils';
type ResponsiveLayout = {lg?: Layout, md?: Layout, sm?: Layout, xs?: Layout, xxs?: Layout};
export type ResponsiveLayout = {lg?: Layout, md?: Layout, sm?: Layout, xs?: Layout, xxs?: Layout};
type Breakpoint = string;
type Breakpoints = {lg?: number, md?: number, sm?: number, xs?: number, xxs?: number};

Expand Down Expand Up @@ -53,8 +53,8 @@ export function getColsFromBreakpoint(breakpoint: Breakpoint, cols: Breakpoints)
* @return {Array} New layout.
*/
export function findOrGenerateResponsiveLayout(layouts: ResponsiveLayout, breakpoints: Breakpoints,
breakpoint: Breakpoint,
lastBreakpoint: Breakpoint, cols: number, verticalCompact: boolean) {
breakpoint: Breakpoint, lastBreakpoint: Breakpoint,
cols: number, verticalCompact: boolean): Layout {
// If it already exists, just return it.
if (layouts[breakpoint]) return layouts[breakpoint];
// Find or generate the next layout
Expand All @@ -69,7 +69,7 @@ export function findOrGenerateResponsiveLayout(layouts: ResponsiveLayout, breakp
}
}
layout = JSON.parse(JSON.stringify(layout || [])); // clone layout so we don't modify existing items
return utils.compact(utils.correctBounds(layout, {cols: cols}), verticalCompact);
return compact(correctBounds(layout, {cols: cols}), verticalCompact);
}

/**
Expand Down
26 changes: 12 additions & 14 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export function compactItem(compareWith: Layout, l: LayoutItem, verticalCompact:
* @param {Array} layout Layout array.
* @param {Number} bounds Number of columns.
*/
export function correctBounds(layout: Layout, bounds: number): Layout {
export function correctBounds(layout: Layout, bounds: {cols: number}): Layout {
let collidesWith = getStatics(layout);
for (let i = 0, len = layout.length; i < len; i++) {
let l = layout[i];
Expand Down Expand Up @@ -141,10 +141,9 @@ export function correctBounds(layout: Layout, bounds: number): Layout {
* @param {Number} id ID
* @return {LayoutItem} Item at ID.
*/
export function getLayoutItem(layout: Layout, id: number): LayoutItem {
id = "" + id;
export function getLayoutItem(layout: Layout, id: number): ?LayoutItem {
for (let i = 0, len = layout.length; i < len; i++) {
if ("" + layout[i].i === id) return layout[i];
if (layout[i].i === id) return layout[i];
}
}

Expand Down Expand Up @@ -193,16 +192,16 @@ export function getStatics(layout: Layout): Array<LayoutItem> {
* @param {Boolean} [isUserAction] If true, designates that the item we're moving is
* being dragged/resized by th euser.
*/
export function moveElement(layout: Layout, l: LayoutItem, x: number, y: number, isUserAction: boolean): Layout {
export function moveElement(layout: Layout, l: LayoutItem, x: ?number, y: ?number, isUserAction: ?boolean): Layout {
if (l.static) return layout;

// Short-circuit if nothing to do.
if (l.y === y && l.x === x) return layout;

let movingUp = l.y > y;
let movingUp = y && l.y > y;
// This is quite a bit faster than extending the object
if (x !== undefined) l.x = x;
if (y !== undefined) l.y = y;
if (x != null) l.x = x;
if (y != null) l.y = y;
l.moved = true;

// If this collides with anything, move it.
Expand Down Expand Up @@ -246,7 +245,7 @@ export function moveElement(layout: Layout, l: LayoutItem, x: number, y: number,
* by the user.
*/
export function moveElementAwayFromCollision(layout: Layout, collidesWith: LayoutItem,
itemToMove: LayoutItem, isUserAction: boolean): Layout {
itemToMove: LayoutItem, isUserAction: ?boolean): Layout {

// If there is enough space above the collision to put this element, move it there.
// We only do this on the main collision as this can get funky in cascades and cause
Expand All @@ -257,7 +256,8 @@ export function moveElementAwayFromCollision(layout: Layout, collidesWith: Layou
x: itemToMove.x,
y: itemToMove.y,
w: itemToMove.w,
h: itemToMove.h
h: itemToMove.h,
i: -1
};
fakeItem.y = Math.max(collidesWith.y - itemToMove.h, 0);
if (!getFirstCollision(layout, fakeItem)) {
Expand Down Expand Up @@ -330,10 +330,8 @@ export function synchronizeLayoutWithChildren(initialLayout: Layout, children: A
for (let i = 0, len = children.length; i < len; i++) {
let child = children[i];
// Don't overwrite if it already exists.
let exists = getLayoutItem(initialLayout, child.key);
let exists = getLayoutItem(initialLayout, parseInt(child.key || "1" /* FIXME satisfies Flow */, 10));
if (exists) {
// Ensure 'i' is always a string
exists.i = '' + exists.i;
layout.push(exists);
continue;
}
Expand All @@ -350,7 +348,7 @@ export function synchronizeLayoutWithChildren(initialLayout: Layout, children: A
}
} else {
// Nothing provided: ensure this is added to the bottom
layout.push({w: 1, h: 1, x: 0, y: bottom(layout), i: child.key});
layout.push({w: 1, h: 1, x: 0, y: bottom(layout), i: parseInt(child.key || "1", 10)});
}
}

Expand Down

0 comments on commit 5984775

Please sign in to comment.