Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
plandem committed Feb 14, 2016
0 parents commit 8fcb7bc
Show file tree
Hide file tree
Showing 7 changed files with 285 additions and 0 deletions.
46 changes: 46 additions & 0 deletions actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as types from './constants'

export function compact(grid) {
return { type: types.COMPACT, grid}
}

export function add(grid, settings = { }) {
return { type: types.ADD, grid, settings }
}

export function remove(grid, id) {
return { type: types.REMOVE, grid, id }
}

export function update(grid, item) {
return { type: types.UPDATE, grid, item }
}

export function select(grid, id) {
return { type: types.SELECT, grid, id }
}

export function deselect(grid) {
return { type: types.DESELECT, grid }
}

export function breakpointChange(grid, breakpoint, cols) {
return { type: types.BREAKPOINT_CHANGE, grid, breakpoint, cols }
}

export function widthChange(grid, width, margin, cols) {
return { type: types.WIDTH_CHANGE, grid, width, margin, cols }
}

export function layoutChange(grid, layout, allLayouts) {
return { type: types.LAYOUT_CHANGE, grid, layout, allLayouts}
}

const commonEvent = (type) => (grid, layout, oldItem, newItem, placeholder, e, element) => { return { type: type, grid, layout, oldItem, newItem, placeholder, e, element } };

export const dragStart = commonEvent(types.DRAG_START);
export const dragStop = commonEvent(types.DRAG_STOP);
export const drag = commonEvent(types.DRAG);
export const resizeStart = commonEvent(types.RESIZE_START);
export const resizeStop = commonEvent(types.RESIZE_STOP);
export const resize = commonEvent(types.RESIZE);
26 changes: 26 additions & 0 deletions constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const COMPACT = "@@redux-grid/compact";

export const ADD = "@@redux-grid/add";
export const UPDATE = "@@redux-grid/update";
export const REMOVE = "@@redux-grid/remove";

export const SELECT = "@@redux-grid/select";
export const DESELECT = "@@redux-grid/deselect";

export const DRAG = "@@redux-grid/drag";
export const DRAG_START = "@@redux-grid/drag-start";
export const DRAG_STOP = "@@redux-grid/drag-stop";

export const RESIZE = "@@redux-grid/resize";
export const RESIZE_START = "@@redux-grid/resize-start";
export const RESIZE_STOP = "@@redux-grid/resize-stop";

export const BREAKPOINT_CHANGE = "@@redux-grid/breakpoint-change";
export const LAYOUT_CHANGE = "@@redux-grid/layout-change";
export const WIDTH_CHANGE = "@@redux-grid/width-change";






30 changes: 30 additions & 0 deletions grid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { connect } from 'react-redux';
import * as actions from './actions';

export const reduxGrid = (name, options = { withRef: true }) => component => {
function mapDispatchToProps(dispatch) {
return {
addItem: (settings) => dispatch(actions.add(name, settings)),
removeItem: (id) => dispatch(actions.remove(name, id)),
updateItem: (item) => dispatch(actions.update(name, item)),
select: (id) => dispatch(actions.select(name, id)),
deselect: () => dispatch(actions.deselect(name)),
compact: () => dispatch(actions.compact(name)),
onDragStart:(id, x, y, e) => dispatch(actions.dragStart(name, id, x, y, e)),
onDrag: (id, x, y, e) => dispatch(actions.drag(name, id, x, y, e)),
onDragStop: (id, x, y, e) => dispatch(actions.dragStop(name, id, x, y, e)),
onResizeStart: (id, w, h, e) => dispatch(actions.resizeStart(name, id, w, h, e)),
onResize: (id, w, h, e) => dispatch(actions.resize(name, id, w, h, e)),
onResizeStop: (id, w, h, e) => dispatch(actions.resizeStop(name, id, w, h, e)),
onBreakpointChange: (breakpoint, cols) => dispatch(actions.breakpointChange(name, breakpoint, cols)),
onLayoutChange: (layout, allLayout) => dispatch(actions.layoutChange(name, layout, allLayout)),
onWidthChange: (width, margin, cols) => dispatch(actions.widthChange(name, width, margin, cols))
}
}

return connect(
state => ({ ...state[name] }),
mapDispatchToProps, null,
options
)(component);
};
11 changes: 11 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { createGridReducer } from './reducer';
import { compact, autoincrement } from './utils';
import * as actions from './actions';
import { reduxGrid } from './grid';

export { createGridReducer };
export { reduxGrid };
export { actions };
export { compact };
export { autoincrement };

29 changes: 29 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "redux-react-grid-layout",
"version": "1.0.0",
"description": "Redux connector for react-grid-layout",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/plandem/redux-react-grid-layout.git"
},
"keywords": [
"grid",
"redux",
"react"
],
"author": "Andrey Gayvoronsky",
"license": "MIT",
"bugs": {
"url": "https://github.com/plandem/redux-react-grid-layout/issues"
},
"homepage": "https://github.com/plandem/redux-react-grid-layout#readme",
"dependencies": {
"react": "^0.14.7",
"react-redux": "^4.4.0",
"redux": "^3.3.1"
}
}
58 changes: 58 additions & 0 deletions reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as types from'./constants';
import { compact_full, compact_none, autoincrement } from'./utils';

const initialState = {
layout: [],
selected: null
};

function createItem(state, next, settings) {
const id = next(state);
return {
next: id,
layout: state.layout.concat({
i: settings.id || id.toString(),
x: settings.x || 0,
y: settings.y || state.layout.reduce((max_y, item) => Math.max(max_y, item.y + item.h), 0),
w: settings.w || 1,
h: settings.h || 1
}
)
};
}

function removeItem(state, id) {
return state.layout.filter(item => (item.i !== id) )
}

function updateItem(state, newItem) {
return state.layout.map(item => (newItem.i == item.i ? newItem : item))
}

export function createGridReducer(grid, next = autoincrement, compactor = compact_full) {
return (state = initialState, action) => {
//TODO: think about testing for action type in case if 'grid' property of action is using by other reducer
if(action.grid != grid) {
return state;
}

switch (action.type) {
case types.ADD:
return Object.assign({}, state, createItem(state, next, action.settings));
case types.REMOVE:
return Object.assign({}, state, { layout: compactor(removeItem(state, action.id)) });
case types.UPDATE:
return Object.assign({}, state, { layout: compactor(updateItem(state, action.item)) });
case types.LAYOUT_CHANGE:
return Object.assign({}, state, { layout: compactor(action.layout) });
case types.COMPACT:
return Object.assign({}, state, { layout: compactor(state.layout) });
case types.SELECT:
return Object.assign({}, state, { selected: action.id });
case types.DESELECT:
return Object.assign({}, state, { selected: null });
default:
return state;
}
}
}
85 changes: 85 additions & 0 deletions utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
export const autoincrement = state => { return (state.next || 0) + 1 };

function compact(layout, vertical = true, horizontal = true) {
if(!vertical && !horizontal) {
return layout;
}

const max_x = layout.reduce((max_x, item) => Math.max(max_x, item.x + item.w), 0);
const max_y = layout.reduce((max_y, item) => Math.max(max_y, item.y + item.h), 0);
const matrix = [];
const updated = new Array(layout.length).fill(false);

for(let y = 0; y < max_y; y++) {
matrix.push(new Array(max_x).fill(undefined));
}

//fill layout matrix
layout.forEach(function(item) {
for(let i_y = item.y, i_y_max = item.y + item.h; i_y < i_y_max; i_y++) {
for(let i_x = item.x, i_x_max = item.x + item.w; i_x < i_x_max; i_x++) {
matrix[i_y][i_x] = item.i;
}
}
});

//compact vertical
if(vertical) {
let compressed = 0;
for (let y = 0; y < max_y; y++) {
let is_empty_row = true;
for (let x = 0; x < max_x; x++) {
if (matrix[y][x] !== undefined) {
is_empty_row = false;
break;
}
}

if (is_empty_row) {
const compressed_y = y - compressed;
layout.forEach((item, i) => {
if (item.y > compressed_y) {
item.y--;
updated[i] = true;
}
});

compressed++;
}
}
}

//compact horizontal
if(horizontal) {
let compressed = 0;
for (let x = 0; x < max_x; x++) {
let is_empty_col = true;
for (let y = 0; y < max_y; y++) {
if (matrix[y][x] !== undefined) {
is_empty_col = false;
break;
}
}

if (is_empty_col) {
const compressed_x = x - compressed;
layout.forEach((item, i) => {
if (item.x > compressed_x) {
item.x--;
updated[i] = true;
}
});

compressed++;
}
}
}

console.log(layout.map((item, i) => updated[i] ? { ...item } : item));
return layout.map((item, i) => updated[i] ? { ...item } : item);
}

export const compact_vertical = layout => compact(layout, true, false);
export const compact_horizontal = layout => compact(layout, false, true);
export const compact_full = layout => compact(layout);
export const compact_none = layout => layout;

0 comments on commit 8fcb7bc

Please sign in to comment.