diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..c2cdfb8ada
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,21 @@
+# EditorConfig helps developers define and maintain consistent
+# coding styles between different editors and IDEs
+# editorconfig.org
+
+root = true
+
+
+[*]
+
+# Change these settings to your own preference
+indent_style = space
+indent_size = 2
+
+# We recommend you to keep these unchanged
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.travis.yml b/.travis.yml
index 04be86e827..97c86ac117 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,6 @@ node_js:
- '0.10'
notifications:
- irc: "chat.freenode.net#ui-grid"
webhooks:
urls:
- https://webhooks.gitter.im/e/c9dc628573cc153706fa
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a162c3356..69202ff08c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,64 @@
+
+### v3.0.0-rc.21 (2015-04-28)
+
+
+#### Bug Fixes
+
+* **Expandable:** Run with lower priority than ngIf ([949013c3](http://github.com/angular-ui/ng-grid/commit/949013c332c5af1b3e37b1d3fa515dfd96c8acb2), closes [#2804](http://github.com/angular-ui/ng-grid/issues/2804))
+* **RTL:**
+ * Use Math.abs for normalizing negatives ([4acbdc1a](http://github.com/angular-ui/ng-grid/commit/4acbdc1a58d8043d60e3a62d1126b0f69bc6ee86))
+ * Use feature detection to determine RTL ([fbb36319](http://github.com/angular-ui/ng-grid/commit/fbb363197ab3975411589dfa0904495f861795c0), closes [#1689](http://github.com/angular-ui/ng-grid/issues/1689))
+* **cellNav:** fix null ref issue in navigate event for oldRowColumn scrollTo should not setF ([02b05cae](http://github.com/angular-ui/ng-grid/commit/02b05cae6d5385e01d00f812662f16009130c647))
+* **pinning:** restore correct width state ([4ffaaf26](http://github.com/angular-ui/ng-grid/commit/4ffaaf26774bae7f52bf4956f45243f6c7dd53a3))
+* **scrolling:** Fix for #3260 atTop/Bottom/Left/Right needed tweaking ([89461bcb](http://github.com/angular-ui/ng-grid/commit/89461bcbcfdfc527655c398df19555738fa9bd63))
+* **selection:**
+ * allow rowSelection to be navigable if using cellNav; allow rowSelection via the ([95ce7b1b](http://github.com/angular-ui/ng-grid/commit/95ce7b1b694b23f1a7506cf4f6a32d0ae384697c))
+ * allow rowSelection to be navigable if using cellNav; allow rowSelection via the ([3d5d6031](http://github.com/angular-ui/ng-grid/commit/3d5d603178f0fcb4cc2abab6ce637c1dd6face8d))
+* **uiGrid:**
+ * Use margins rather than floats for pinning ([1373b99e](http://github.com/angular-ui/ng-grid/commit/1373b99e1e1680184270d61bca88124efd7a4c14), closes [#2997](http://github.com/angular-ui/ng-grid/issues/2997), [#NaN](http://github.com/angular-ui/ng-grid/issues/NaN))
+ * Wait for grid to get dimensions ([e7dfb8c2](http://github.com/angular-ui/ng-grid/commit/e7dfb8c2dfac69bb3a38f7253062367671fec56d))
+* **uiGridColumnMenu:** Position relatively ([9d918052](http://github.com/angular-ui/ng-grid/commit/9d9180520d8d6fd16b897ba4b9fbfc4bb4860ea9), closes [#2319](http://github.com/angular-ui/ng-grid/issues/2319))
+* **uiGridFooter:** Watch for col change ([1f9100de](http://github.com/angular-ui/ng-grid/commit/1f9100defb1489bed46515fb859aed9c9a090e73), closes [#2686](http://github.com/angular-ui/ng-grid/issues/2686))
+* **uiGridHeader:**
+ * Use parseInt on header heights ([98ed0104](http://github.com/angular-ui/ng-grid/commit/98ed01049015b22caddb651b1884f6e383fc58aa))
+ * Allow header to shrink in size ([7c5cdca1](http://github.com/angular-ui/ng-grid/commit/7c5cdca1f471a0a3c1ef340fe65af268df68cae3), closes [#3138](http://github.com/angular-ui/ng-grid/issues/3138))
+
+
+#### Features
+
+* **saveState:** add pinning to save state ([b0d943a8](http://github.com/angular-ui/ng-grid/commit/b0d943a82a1d5c64808b759c8b96833e66380b02))
+
+
+#### Breaking Changes
+
+* gridUtil will no longer calculate dimensions of hidden
+elements
+ ([e7dfb8c2](http://github.com/angular-ui/ng-grid/commit/e7dfb8c2dfac69bb3a38f7253062367671fec56d))
+* Two events are now emitted on scroll:
+
+ grid.api.core.ScrollBegin
+ grid.api.core.ScrollEnd
+
+ Before:
+ grid.api.core.ScrollEvent
+ After:
+grid.api.core.ScrollBegin
+
+ScrollToIfNecessary and ScrollTo moved from cellNav to core and grid removed from arguments
+Before:
+grid.api.cellNav.ScrollToIfNecessary(grid, gridRow, gridCol)
+grid.api.cellNav.ScrollTo(grid, rowEntity, colDef)
+
+After:
+grid.api.core.ScrollToIfNecessary(gridRow, gridCol)
+grid.api.core.ScrollTo(rowEntity, colDef)
+
+GridEdit/cellNav
+When using cellNav, a cell no longer receives focus. Instead the viewport always receives focus. This eliminated many bugs associated with scrolling and focus.
+
+If you have a custom editor, you will no longer receive keyDown/Up events from the readonly cell. Use the cellNav api viewPortKeyDown to capture any needed keydown events. see GridEdit.js for an example
+ ([052c2321](http://github.com/angular-ui/ng-grid/commit/052c2321f97b37f860c769dcbd2e8d9094cf2bbf))
+
### v3.0.0-rc.20 (2015-02-24)
diff --git a/bower.json b/bower.json
index 185d4c0afb..8ee4fd2a0b 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "angular-ui-grid",
- "version": "3.0.0-rc.20",
+ "version": "3.0.0-rc.21",
"homepage": "http://ui-grid.info",
"repository": {
"type": "git",
diff --git a/misc/api/design-rendering-cycle.ngdoc b/misc/api/design-rendering-cycle.ngdoc
new file mode 100644
index 0000000000..a0a6feb4df
--- /dev/null
+++ b/misc/api/design-rendering-cycle.ngdoc
@@ -0,0 +1,73 @@
+@ngdoc overview
+@name Rendering Cycle
+@module
+@description
+
+The core grid rendering cycle is executed whenever the grid needs re-rendering. There are a number of core methods,
+with some of those methods able to be called individually.
+
+### Current
+The key method is `grid.refresh`. This method updates the rows and columns in the grid, then redraws and resizes the grid.
+
+ - grid.refresh
+ - rowsProcessors
+ - setVisibleRows
+ - columnsProcessors
+ - setVisibleColumns
+ - redrawInPlace
+ - refreshCanvas
+
+By preference grid.refresh is called through a debounce function - grid.queueGridRefresh. If you use this method you are
+telling the grid that you want a refresh, but you're allowing the grid to consolidate all refreshes from the current digest cycle
+and process just once.
+
+A similar method, `grid.refreshRows` also exists, this is the same as grid.refresh except that it doesn't run `columnsProcessors`
+or `setVisibleColumns`.
+
+The rows and columns processors are focused on ordering and determining the visibility of columns and rows. They include functions
+such as sorting and filtering (impacting order and visibility of rows), grouping rows (which adds extra rows, and changes the ordering
+and widths of columns), and pinning, which changes which render container particular columns are in.
+
+`redrawInPlace` determines the correct scroll percentage in the grid, and therefore which of the rows and columns should currently
+be visible in the viewport.
+
+`refreshCanvas` is a complicated method that determines the sizing of each of the grid elements. In some cases it is currently iterative,
+for example it determines header height by rendering each of the column headers, and determining the maximum rendered height. This largely
+appears to be to accomodate filters.
+
+ - refreshCanvas
+ - buildStyles
+ - $timeout - calcHeaders (this is inline - should it be a style computation? It isn't a promise, and doesn't wait on the buildStyles
+ promise, but it does run in a timeout. Conversely, it creates a promise that it resolves - but it doesn't wait for the header calc to
+ complete before resolving the promise)
+ - may call buildStyles again if it decides headerHeight has changed
+
+The style builders include:
+
+- `GridRenderContainer.updateColumnWidths`, which calculates column widths based on the defined settings, including resolving * and ** etc. No rendering
+ is involved - all based on the availableWidth. This may be the source of some of the iteration - because availableWidth must in some way be
+ based on columnWidth - the canvas doesn't really have an available width. I also have question on why we calculate widths on the grid
+ and not on the renderContainer, that may be another source of iteration. Having said that, things like % and * probably apply to the
+ full grid width, not to just a container, and we wouldn't expect a column to change width when it changed container (e.g. when we pinned it)
+- `uiGridRenderContainer.update()`, which is called for each renderContainer. It determines the
+width of each column in the render container, and the width of the overall render container.
+- `Grid.prototype.getFooterStyles()`, sets the columnFooterHeight and the gridFooterHeight based on fixed values declared in the options
+- when there are multiple renderContainers (e.g. a left container), the non-body render containers appear to execute first
+- `ui-pinned-container.updateContainerDimensions()`: sets the width of a pinned container. How does this interact with render container width?
+
+### Vision
+The vision is to make the style calculations more deterministic, and remove any iteration or other dependencies. A single pass through
+refreshCanvas should return a correctly sized grid.
+
+To achieve this, we really need to:
+
+- calculate all sizing in code, without reference to the sizing of rendered grid elements. We already do most of this for rows
+ and columns, the main gap seems to be grid header
+- we could reference rendered size to determine the grid's available size (if we want to), which could allow the grid to be more
+ responsive. Probably we already do this.
+- calculate the column widths and element heights
+- layout all the columns - what render container they're in etc, then size the render containers
+- calculate the overall grid sizing based on all the elements (headerHeight, footerHeight, container widths etc)
+- render
+
+Thinking only at this stage!!
diff --git a/misc/demo/grid-save.html b/misc/demo/grid-save.html
new file mode 100644
index 0000000000..8a19c65df6
--- /dev/null
+++ b/misc/demo/grid-save.html
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Grid
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/misc/demo/modal.html b/misc/demo/modal.html
new file mode 100644
index 0000000000..60ebcc34ad
--- /dev/null
+++ b/misc/demo/modal.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+