Compare commits

...
216 Commits
Author SHA1 Message Date
Tanner Linsley 8004e7a85f 6.5.2 2017-08-02 13:25:44 -06:00
Tanner Linsley 84af88916a Fix Typo 2017-08-02 13:16:54 -06:00
Tanner Linsley 9846bf1905 Provide onClick handleOriginal function
Fixes #406
2017-08-02 13:15:16 -06:00
Tanner Linsley bf88dda5dc Revert to page 1 on filter change
Fixes #273
2017-08-02 12:36:49 -06:00
Tanner Linsley 7f5779a833 Some simple event propagation fixes (but not the 100% fix) 2017-08-02 12:10:46 -06:00
Tanner Linsley 8792bd95a0 Move onFetchData for better timing and reliability
Fixes #294
2017-08-02 08:59:54 -06:00
ldsteinandTanner Linsley 098b1fec51 Max width NaN fix (#415)
* Added button to reset table state in Controlled Component story

* Fix maxWidth style when value is NaN

* code formatting
2017-08-01 21:27:40 -06:00
Tanner Linsley 750cfe3ac4 Fix Linting 2017-07-31 10:37:12 -06:00
Tanner Linsley 370f443347 Fix pivot header groups
Fixes #376
2017-07-31 10:29:41 -06:00
Tanner Linsley 67f8c9adf1 Cleanup 2017-07-31 09:36:29 -06:00
Tanner Linsley 867cc25899 Fixed display of inputs and checkboxes
Fixes #398
2017-07-31 09:27:03 -06:00
Caroline ShawandTanner Linsley 639630946c Update README to reflect updates (#400) 2017-07-25 14:01:17 -06:00
qmorelandTanner Linsley 688afd2947 [refs #321]: correct makePathArray function in utils (#326) 2017-07-19 14:43:32 -06:00
Tanner LinsleyandGitHub bbebf02a55 Update README.md 2017-07-17 15:01:04 -06:00
Tanner LinsleyandGitHub f4d3c2d7bb Update README.md 2017-07-17 15:00:31 -06:00
Tanner LinsleyandGitHub f8634e771e Update README.md 2017-07-11 14:32:10 -06:00
emyarodandTanner Linsley ba74ab3ce8 Fix typo (#380) 2017-07-08 10:22:24 -06:00
Tanner Linsley 30ed0c82fc 6.5.1 2017-07-05 17:09:11 -06:00
Tanner Linsley 62f19aecf0 Fix: makeTemplateComponent now supports displayName
Fixes #289
2017-07-05 17:08:08 -06:00
Tanner Linsley 8dc4caff45 Fix: column.getProps().rest props are now applied correctly 2017-07-05 16:58:14 -06:00
Tanner Linsley c2e935d75b Fix: defaultExpanded now works correctly
Fixes #372
2017-07-05 16:58:00 -06:00
Tanner Linsley f9a1cfae1e 6.5.0 2017-07-05 10:31:56 -06:00
Tanner Linsley 5ac2c1779d Feature: column.filterAll + docs 2017-07-05 10:31:50 -06:00
Tanner Linsley 3b2432f535 Formatting with prettier + eslint 2017-07-03 09:48:24 -06:00
Jacob CofmanandTanner Linsley 7aa98887ef fix for issue #240 (#363) 2017-07-03 09:14:45 -06:00
Aaron SchwartzandTanner Linsley d26d82ecfb Fix source code in FixedHeader example (#369) 2017-07-03 09:13:15 -06:00
Tanner Linsley b76f9c956d 6.4.0 2017-06-19 11:34:29 -06:00
Tanner Linsley 2e3743b75f Feature: PadRowComponent prop 2017-06-19 11:34:21 -06:00
Tanner Linsley fdb3e77b00 6.3.0 2017-06-09 21:02:37 -06:00
Tanner Linsley d9248cef2b Added defaultSortDesc prop and formatted with prettier + project's eslint 2017-06-09 21:02:28 -06:00
Tanner Linsley f4704b146c 6.2.0 2017-06-07 21:57:54 -06:00
Tanner Linsley 004186af24 No old storybook files 2017-06-07 21:57:37 -06:00
Mayank JethvaandTanner Linsley 0d0e239baa Top and Bottom Pagination (#283)
* added top and bottom pagination, included story

* version bump

* linting

* fixes

* PR fixes

* lint and fixes

* update story

* removed unused attr
2017-06-05 17:45:04 -06:00
Stanislav DzhusandTanner Linsley f61b19cb8a fix property name (#290) 2017-05-30 08:45:58 -06:00
stefaniapavelandTanner Linsley e1a46fb77e fix IE select visual bug (#301) 2017-05-30 08:44:32 -06:00
ldsteinandTanner Linsley a9db5b1ac6 Add minRows to list of available props (#295)
* Added showPaddedRows prop

* Added minRows to defaultProps, added to documentation.

* Revert "Added showPaddedRows prop"

This reverts commit be89c4913f11df8b322ac9f65e3500c9539f838f.

* Removed minRows from defaultProps
2017-05-26 22:17:41 -06:00
Tanner Linsley 846fc0d84d 6.0.5 2017-05-19 16:27:53 -06:00
Tanner Linsley 87610c83fa Revert overflow styles 2017-05-19 16:27:48 -06:00
Tanner Linsley a58f5c4de2 Update docs 2017-05-19 16:26:48 -06:00
Tanner Linsley 1995bba652 6.0.4 2017-05-19 12:06:48 -06:00
Tanner Linsley 680747d1d0 Fixed: scrollbar no longer offsets flex widths, documentation deps fixed 2017-05-19 12:06:35 -06:00
Tanner Linsley e70b29066b 6.0.3 2017-05-16 11:50:41 -06:00
Tanner Linsley 9d82cee707 Better vertical responsiveness & Fixed Header example 2017-05-16 11:50:34 -06:00
Tanner Linsley db1edf119d 6.0.2 2017-05-16 11:16:34 -06:00
theCmakerandTanner Linsley c5fa476b6d Fixed issue #210 - Ignore filters on hidden columns. (#265)
* Fixed issue #210 - Ignore filters on hidden columns.

* Fixed issue #210 - Ignore filters on hidden columns
2017-05-16 09:17:36 -06:00
atkawa7andTanner Linsley 550a1f7107 Fix default sorting documentation (#270) 2017-05-16 09:09:09 -06:00
Mark HatchandTanner Linsley 42e1a12ea9 Height on pagination button removed (#275) 2017-05-15 22:36:42 -06:00
Tanner Linsley 15945d28a1 Always keep track of internal state regardless of controlled props, but allow prop overrides 2017-05-15 21:22:58 -06:00
Tanner Linsley eaa7215674 Update Readme 2017-05-14 02:22:28 -06:00
Tanner Linsley d2835b9e14 Fix storybook link 2017-05-14 02:22:05 -06:00
Tanner Linsley 5691fa2e7a Upgrade react-story 2017-05-14 02:18:44 -06:00
Tanner Linsley f4aba6a008 Upgrade react-story 2017-05-14 01:36:07 -06:00
Tanner Linsley 7bce5a8958 Update Docs 2017-05-14 01:28:32 -06:00
Tanner Linsley 875d3d93d6 Update Contributing 2017-05-14 01:18:35 -06:00
Tanner Linsley a0ede1593b Pass standard code style 2017-05-14 01:15:06 -06:00
Tanner Linsley 0d43b6d601 Fix stories 2017-05-14 01:10:56 -06:00
Tanner Linsley 9dbd485cad Migrate docs to CRA + react-story + netlify 2017-05-14 01:03:46 -06:00
Tanner Linsley ee5fae8c6f 6.0.1 2017-05-12 11:42:55 -06:00
Aaron SchwartzandTanner Linsley 95164311fa Fix default sort algorithm (#268) 2017-05-12 11:42:13 -06:00
Tanner Linsley 49c5a3d5e1 Revert "Init"
This reverts commit f27ec1fb34.
2017-05-11 19:03:31 -06:00
Tanner Linsley f27ec1fb34 Init 2017-05-11 18:19:17 -06:00
Tanner Linsley dd26802535 Updated Docs 2017-05-11 14:47:44 -06:00
terencechowandTanner Linsley 97e560cb0f when you have no data pages shows as 0 instead of 1 (#248)
see https://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Custom%20%22No%20Data%22%20Text&full=0&down=0&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel
2017-05-11 13:43:05 -06:00
Tanner LinsleyandGitHub 2ba0bf73ad 6.0.0
* Use separate columns for Pivots and Expanders, more render options

* Better expanding and aggregation control

* Updated Renderer Keys and Stories (+ story cleanup)

* Fixed Typo

* Resizing Fixes, custom sorting, new api names

* +Key constants, prop/callback changes, controllable filters and resizing, subRow + pivoting expansion

* Remove console.log

* Trying generalize expanders to work on any column

* Fix up stories.

* Better custom sorting

* Finish fixing up stories with better source

* Fix SubComponent Story

* Updated Changelog

* 6.0.0

* Use Correct PivotingOptions source

* Handle edge cases in expandable hover states and event handlers

* Add defaultExpanded prop

* Rename sorting->sorted, onSortingChange->onSortedChange, defaultSorting->defaultSorted

* filtering->filtered, onFilteringChange->onFilteredChange, defaultFiltering->defaultFiltered

* Rename expandedRows->expanded, onExpandRow->onExpanded

* Rename resizing->resized, defaultResizing->defaultResized, onResize->onResizedChange

* Rename onExpanded->onExpandedChange

* Cleanup Readme

* Standardize global and column level resizable and sortable properties

* Rename showFilters->filterable, hideFilter->filterable

* Cleanup Changelog and lint errors

* Remove unused prop

* Remove unused prop from readme.
2017-05-11 13:10:17 -06:00
Miha ValencicandTanner Linsley ad7d31cd39 Add column id to the rowInfo object (#253)
* Add column id to the rowInfo object (passed to render). Resolves #237

* Creating a new object instead of modifying existing rowInfo; Refs #253

* Code style compliance. Refs #253
2017-05-06 10:33:17 -06:00
wonyoungandTanner Linsley ddee18cf86 Update README.md (#213)
* Update README.md

Bug fix in custom props example

* Update README.md

Bug fix in custom column props example
2017-05-05 17:22:48 -06:00
Austin HuntandTanner Linsley 1757b4dd9f Fixed documentation to match the actual implementation settings. Sorting objects use a desc prop not a asc prop. (#239) 2017-05-05 17:22:09 -06:00
Aaron SchwartzandGitHub 9d9b1fdee4 Enhance pivots (#224)
* Prevent transitions while resizing for a smoother effect.
* Disable text selection when resizing columns
* Use PivotValueComponent instead of pivotRender
* Add changelog file
2017-05-05 12:51:17 -07:00
Aaron SchwartzandGitHub ab1c020ad3 Fix sorting indicator or pivot columns. 2017-04-20 16:13:17 -07:00
Tanner Linsley 0c3f2f2cd1 5.6.0 2017-04-20 16:44:31 -06:00
Tanner Linsley 03538823e9 Updated Docs 2017-04-20 16:44:24 -06:00
Aaron SchwartzandTanner Linsley bc7005db99 Enhanced expander and pivot (#215)
* Convert expander column to be more like a regular column.

* Update story.

* Simplify setting render on defaultExpander.

* Add more control over expander and pivot columns using the  column.

* Fix default filtering on pivot column.

* Add comments.
2017-04-20 16:41:50 -06:00
Tanner Linsley 42b5f5bb18 Convert to use es6 classes for react 15.5.x compat 2017-04-18 11:33:22 -06:00
Tanner Linsley 5ec616c2a3 Add CDN to docs 2017-04-18 09:48:38 -06:00
Tanner Linsley c16df80938 Added codepen example 2017-04-17 12:23:14 -06:00
Tanner Linsley a1e724c483 5.5.3 2017-04-17 12:00:29 -06:00
Tanner Linsley 741660c915 Use webpack to compile umd 2017-04-17 12:00:17 -06:00
Tanner Linsley 1f8062501f Better npm scripts for ci and publishing 2017-04-17 11:27:20 -06:00
Tanner Linsley fb51afd0ae Keep tags up to date with releases 2017-04-17 09:30:02 -06:00
Tanner Linsley a64c6a3a76 5.5.2 2017-04-17 09:29:06 -06:00
Tanner Linsley f502ef4e2b Immutablely decorate with _viewIndex
#203
2017-04-17 09:28:31 -06:00
theCmakerandTanner Linsley c58c96c84f Fixed issue #14 Default CSS overwrites the checkbox appearance if included into a custom cell. (#197) 2017-04-17 09:15:53 -06:00
Tanner Linsley 7202776c86 5.5.1 2017-04-13 10:49:15 -06:00
Mike DeVitaandGitHub 734ba48e9c Update ISSUE_TEMPLATE.md
fix the system information section to use bulleted lists
2017-04-10 10:12:04 -07:00
Alejandro BrozzoandTanner Linsley db84ecf789 Fixed code highlights (#179) 2017-04-10 10:21:31 -06:00
AlejandroandTanner Linsley 50668fe90f Avoid page refresh if same page, set NaN to current page (#178)
* Avoid page refresh if same page, set NaN to current page

* Fixed styling rule errors
2017-04-07 17:07:42 -06:00
Aaron SchwartzandGitHub 52f2c9fdac Fix descending sort being non-deterministic
Descending sort would sort differently for the same data on rerender for items that evaluated to the same value.
2017-04-06 15:25:56 -07:00
Tanner Linsley 3b39f523be 5.5.0 2017-04-05 18:51:31 -06:00
Aaron SchwartzandTanner Linsley 9d85981c5b Resize columns (#170)
* Add column resizing for non pivot columns.

* Fixing resizing UI issues and mobile functionality.

* Remove calling onChange during resize events so that server example doesn't refetch data every time a column resizes.
2017-04-05 17:47:55 -06:00
Eric AbbottandTanner Linsley b779a98d7a Change precedence in 'getResolvedState' (#166)
* Change precedence in 'getResolvedState'
  * Previously existing props would overwrite passed in state
  * Now passed in state gets precedence

* added a controlled table example to storybook
2017-04-05 01:10:17 -06:00
Jolyon RussandTanner Linsley 1f4c9afd2b Updated README - wrapped example in render function (#168) 2017-04-04 13:24:03 -06:00
Aaron SchwartzandTanner Linsley cef7fbd780 Add filterRender column option to customize the filter that is shown (#162)
* Add filterRender column option to completely customize the filter that is shown

* Refactor filterRender as a defaultProp.
2017-03-31 15:41:57 -06:00
Tanner Linsley e8ebf7c780 5.4.1 2017-03-30 17:03:47 -06:00
Aaron SchwartzandTanner Linsley ac20220d55 Set page to max page available if data changes and has less pages than before (#160)
* Add column filtering.

* Fix javascript warning from yarn test. Compile storybook and docs.

* Pass standard linting

* Add support for filtering pivot columns.

* Build distribution files.

* Set page to max page available if data changes and has less pages than before.

Closes #159
2017-03-30 17:02:39 -06:00
Tanner Linsley 9acf8f37eb 5.4.0 2017-03-30 10:21:59 -06:00
Mike DeVitaandTanner Linsley 64a427d91b fix broken TOC Link (#157)
Custom Cell Header Rendering link was broken in table of contents.
2017-03-30 09:53:52 -06:00
Mike DeVitaandTanner Linsley d21ce226aa create ISSUE_TEMPLATE.md (#158)
hopefully this will alleviate some clutter on issues.
2017-03-30 09:52:40 -06:00
Tanner LinsleyandGitHub 92c9ae2196 minRows now works for datasets larger than 1 page
Closes #154
2017-03-29 18:02:33 -06:00
Aaron SchwartzandTanner Linsley 23a031b48a Add column filtering (#147)
* Add column filtering.

* Fix javascript warning from yarn test. Compile storybook and docs.

* Pass standard linting

* Add support for filtering pivot columns.

* Build distribution files.
2017-03-29 16:46:04 -06:00
Jolyon RussandTanner Linsley bd8b273dea Added an id in the example so it doesn't error (#151) 2017-03-29 07:08:54 -06:00
Tanner Linsley 1a9f0e57b4 5.3.5 2017-03-27 11:57:44 -06:00
Ryan PalermoandTanner Linsley 4c11248c69 switch -sort-asc and -sort-desc in ternary (#138) 2017-03-23 13:49:03 -06:00
Tanner Linsley 784311bcd6 Remove .DS_Store
Closes #126
2017-03-14 12:18:46 -06:00
Deepak Kumar JainandTanner Linsley 7b232cd6b4 Updated the package.json (#124) 2017-03-12 09:29:32 -06:00
MishaandTanner Linsley 533bea77b6 use button type button in pagination to prevent form submitting if using table inside of the form (#122) 2017-03-09 09:14:49 -07:00
MishaandTanner Linsley 218cf42bb2 removed form tag from pagination component to avoid nested forms error (#119) 2017-03-09 07:34:44 -07:00
Wojtek BażantandTanner Linsley 62287d1641 Add extra empty line to get the accessors table to show up nicely on github's main page (#121) 2017-03-09 07:34:22 -07:00
Ryan PalermoandTanner Linsley 10dc68acc1 use Object.getPrototypeOf instead of .prototype (#117) 2017-03-08 11:43:29 -07:00
Michael BridgeandTanner Linsley bd82468852 Pass relevant attributes to footer JSX (#116) 2017-03-08 11:42:12 -07:00
Tanner Linsley 6d28bb2c4d 5.3.4 2017-03-01 15:50:43 -07:00
Tanner Linsley 9e95b331df Feature: Changing defaultSorting now updates the sorting model 2017-03-01 15:50:36 -07:00
TacticalCodingandTanner Linsley f296b075fe Rename CollapseOnPageChange to CollapseOnDataChange (#100)
* Rename CollapseOnPageChange to CollapseOnDataChange to more accurately reflect its purpose.

* Add support for collapseOnPageChange.

* Fix collapseOnPageChange efficiency.
2017-02-27 16:05:07 -07:00
Tanner Linsley a948a9a41e 5.3.3 2017-02-27 10:01:06 -07:00
atlantehandTanner Linsley 08dbe38ced fix number of callback parameters and alignment (#95) 2017-02-27 08:15:45 -07:00
Daniel WinterandTanner Linsley 884058b459 added missing named export for ReactTableDefaults (#93) 2017-02-19 07:09:29 -07:00
Tanner Linsley ee37ad7101 Update Docs 2017-02-16 15:15:47 -07:00
Tanner Linsley 6b384f2a90 5.3.2 2017-02-16 14:02:30 -07:00
Tanner Linsley 782e9efdfb Fix NoData from always showing 2017-02-16 14:02:21 -07:00
Tanner Linsley ff952de830 5.3.1 2017-02-16 12:40:48 -07:00
Tanner Linsley 149b11674b Docs Update 2017-02-16 12:40:43 -07:00
Tanner Linsley 8a362e4d04 Rollback on table partials to fix mounting/unmounting issues 2017-02-16 12:40:12 -07:00
Tanner Linsley 265a5c8753 5.3.0 2017-02-16 10:41:52 -07:00
Tanner Linsley 5155ebad72 Added more customization for functional rendering 2017-02-16 10:41:52 -07:00
Tanner Linsley d7a58450b7 Added support for Column Footers 2017-02-16 10:41:52 -07:00
avnunnandTanner Linsley bb2527e280 Added documentation for column accessors (#82) 2017-02-15 17:39:01 -07:00
Tanner Linsley 6d5207eb4e 5.2.0 2017-02-15 10:07:33 -07:00
Tanner Linsley 0d397e0c29 Update Docs
Fixes #80
2017-02-15 10:07:14 -07:00
Tanner Linsley b15f3ac3b0 Added "noData" component
Fixes #78
2017-02-15 09:55:42 -07:00
Tanner Linsley 48ea0df09d Normalize all JSX callbacks to support functions 2017-02-15 09:54:57 -07:00
Tanner Linsley 403fb7a708 5.1.1 2017-02-13 15:54:59 -07:00
Tanner Linsley ecd5658e4b Better resolve server-side data pages and pagesize 2017-02-13 15:54:47 -07:00
Tanner Linsley 3852227bdd Fix custom cell render to allow pure functions 2017-02-13 15:54:25 -07:00
Tanner Linsley 1fec9b882f 5.1.0 2017-02-10 16:51:47 -07:00
Tanner Linsley 46c4c6fdb2 Doc Updates 2017-02-10 16:46:54 -07:00
Tanner Linsley e702fc80ca defaultSorting changes and doc updates 2017-02-10 16:46:14 -07:00
Tanner Linsley beaa748187 5.0.4 2017-02-10 14:49:04 -07:00
Tanner Linsley cce77d24f2 Retain original data order if no sorting is found 2017-02-10 14:48:55 -07:00
Tanner Linsley 3984a540c1 5.0.3 2017-02-09 10:07:42 -07:00
Tanner Linsley 726fd52753 Adjust current page if available pages dips below current page
Fixes #69
2017-02-09 10:07:42 -07:00
Tanner LinsleyandGitHub 6a6d373526 Update README.md 2017-02-08 08:20:30 -07:00
TacticalCodingandTanner Linsley e11fdab457 Fix 'iterator must have unique key' warning on pivoting tables. (#56) (#66) 2017-02-07 10:31:40 -07:00
Jan ZandTanner Linsley 1e4f838326 'collapseOnChange' and 'freezeWhenExpanded' (#61)
* rough draft of "closeSubComponentOnDataChange" and "preventAutoSortWhenComponentIsOpen"

* changed flag name from ...component to ...subcomponent

* fixed problem with sorting not immediately being applied. passes tests now

* changed var names

* Cleanup and simplification

* Fix deps

* Better freezing strategy

* subcomponent reverse
2017-02-06 15:09:35 -07:00
Tanner Linsley aa48ef57ee 5.0.2 2017-02-03 14:05:32 -07:00
Tanner Linsley 22f79fcd28 Added instance to all custom props callbacks 2017-02-03 14:05:25 -07:00
Tanner Linsley ff8e24760a 5.0.1 2017-02-03 11:07:51 -07:00
Tanner Linsley f1511bd27e Bug fixes and Doc Updates 2017-02-03 11:07:48 -07:00
Tanner Linsley 4733997c26 Updated Docs 2017-02-02 18:17:37 -07:00
Tanner Linsley c3a6e236ae 5.0.0 2017-02-02 18:13:48 -07:00
Tanner Linsley 83200d4e4c Rewrite of dynamic props and stable sorting algorithm 2017-02-02 18:13:40 -07:00
Tanner Linsley 5e16c2cb24 4.4.1 2017-01-27 14:34:59 -07:00
Tanner Linsley 66cee186a3 pivotBy prop now defaults to undefined 2017-01-27 14:34:50 -07:00
Tanner Linsley 55bbf4bf37 Updated Docs 2017-01-27 14:20:51 -07:00
Tanner Linsley 10ce93344c Updated Docs 2017-01-27 14:17:33 -07:00
Tanner Linsley 114621a359 4.4.0 2017-01-27 14:10:57 -07:00
Tanner Linsley 8de0fa420b Better default sorting, column.width support, expander column position 2017-01-27 14:10:47 -07:00
Tanner Linsley aa77193810 Update Docs 2017-01-26 21:26:58 -07:00
Tanner Linsley 92c33de7ac 4.3.0 2017-01-26 21:25:04 -07:00
Tanner Linsley c3fb084550 Feature: Functional Rendering 2017-01-26 21:22:21 -07:00
Tanner Linsley 04c71f17a8 4.2.8 2017-01-26 15:26:38 -07:00
Tanner Linsley 34fa57c4d3 Updated to latest autoprefixer 2017-01-26 15:26:38 -07:00
George LimaandTanner Linsley de1c8a6156 Update README.md (#38)
Bug fix in installation docs
2017-01-23 12:22:11 -07:00
Tanner Linsley ab9d67d2d9 Update Docs 2017-01-23 10:18:30 -07:00
Tanner Linsley dc0713c1d1 4.2.7 2017-01-23 10:16:59 -07:00
Tanner Linsley c1004ee9e9 column.maxWidth support and fixed css autoprefixer warnings
Fixes #34
2017-01-23 10:16:34 -07:00
Tanner Linsley c0098ebc2c 4.2.6 2017-01-22 10:27:29 -07:00
Tanner Linsley 33645b4fea Styling fixes and documentation 2017-01-22 10:26:49 -07:00
Tanner Linsley 3d325dad8d Fix CNAME being overwritten by storybook export 2017-01-20 11:04:53 -07:00
Tanner Linsley f3ee89a514 Doc Update 2017-01-20 10:58:36 -07:00
Tanner Linsley 90001c1b3a Slack and Contributing Updates 2017-01-20 10:18:34 -07:00
Tanner Linsley 8d7b9c2feb Create CNAME 2017-01-19 19:39:11 -07:00
Tanner Linsley f754eb0bd5 4.2.5 2017-01-19 19:38:34 -07:00
Tanner Linsley 66f1b04ba6 Fix utils.groupBy where watch key would cause error in Firefox 2017-01-19 19:37:32 -07:00
Tanner Linsley bea4b366d6 No cname needed 2017-01-18 21:27:15 -07:00
Tanner Linsley 64168eb3ef Updates demo site 2017-01-18 21:22:21 -07:00
Tanner Linsley 77be7c066f Create CNAME 2017-01-18 21:17:11 -07:00
Tanner Linsley e9e69428a2 Updated Docs 2017-01-18 10:22:59 -07:00
Tanner Linsley 3c039789f1 Updated Docs 2017-01-18 10:22:47 -07:00
Tanner Linsley 5865f59129 New Stories 2017-01-18 10:01:34 -07:00
Tanner Linsley c663cce719 Create CNAME 2017-01-18 09:16:35 -07:00
Tanner Linsley a6f803c1a3 Updated Storybook 2017-01-18 09:09:59 -07:00
Tanner Linsley 4a871db71f 4.2.4 2017-01-18 09:08:21 -07:00
Tanner Linsley 505db8d43e Fixed a bug present when no column groups are used. 2017-01-18 09:08:05 -07:00
Tanner Linsley 387f22028a Pass linting 2017-01-17 11:40:14 -07:00
Tanner Linsley f2839dcc6d Docs update 2017-01-17 11:37:50 -07:00
Tanner Linsley 8a74b2b795 Better storybook 2017-01-17 11:36:30 -07:00
Tanner Linsley 9bbdd762e6 Added CNAME 2017-01-17 11:01:48 -07:00
Tanner Linsley 37cf57e1d0 Removed zab 2017-01-17 10:58:25 -07:00
Tanner Linsley cd507d39a4 Docs now serve using Github Pages 2017-01-17 10:48:53 -07:00
Tanner Linsley 4873af8c99 Readme updates 2017-01-17 09:55:41 -07:00
Tanner Linsley 6c05306d99 Readme Updates 2017-01-17 09:17:02 -07:00
Tanner Linsley ac2f9a2467 Readme Updates 2017-01-17 09:15:57 -07:00
Tanner Linsley 69eccc8909 Reamde Updates 2017-01-17 09:13:41 -07:00
Tanner Linsley 721d193883 Remade updates 2017-01-17 08:28:34 -07:00
Tanner Linsley 21cae2416f Readme Update 2017-01-17 07:59:32 -07:00
Tanner Linsley 0bf363aeaf 4.2.3 2017-01-16 15:52:47 -07:00
Tanner Linsley 517702922e Fix padRows key 2017-01-16 15:52:42 -07:00
Tanner Linsley ba1325336f 4.2.2 2017-01-16 15:01:44 -07:00
Tanner Linsley 7bd30b623c Improved Sorting Performance 2017-01-16 15:01:37 -07:00
Tanner Linsley f72fec3cc2 4.2.1 2017-01-16 14:18:20 -07:00
Tanner Linsley a8a0d1bab8 Fix pageSize bug and 1 Million rows example 2017-01-16 14:18:11 -07:00
Tanner Linsley f06caec053 4.2.0 2017-01-16 13:16:00 -07:00
Tanner Linsley 8fa7975ca5 Pivoting & Aggregation 2017-01-16 13:15:56 -07:00
Tanner Linsley e04a2dee69 Pass standard linting 2017-01-13 10:09:28 -07:00
Tanner Linsley e059ceec75 4.1.1 2017-01-13 09:42:16 -07:00
Tanner Linsley 09f425aeb3 Redux package size to 5kb 2017-01-13 09:42:07 -07:00
Tanner Linsley ca038e9a69 4.1.0 2017-01-12 11:06:20 -07:00
Tanner Linsley 75c31b9354 Fully controlled component props and callbacks + docs 2017-01-12 11:06:09 -07:00
Tanner Linsley 4b2fa4e47d ignore react-storybook in testing 2017-01-11 20:04:32 -07:00
Tanner Linsley 76e92de670 4.0.1 2017-01-11 19:59:03 -07:00
Tanner Linsley 3c5ba2843d Bug fixes and readme updates 2017-01-11 19:58:52 -07:00
Tanner Linsley 1cb280942d Updated Readme 2017-01-11 16:47:56 -07:00
Tanner Linsley c8c650c729 Readme Updates 2017-01-11 16:34:36 -07:00
Tanner Linsley 29eda4dc71 4.0.0 2017-01-11 16:23:52 -07:00
Tanner Linsley e5689bc9d4 New core styling, sub-components, React-Storybook instead of jumpsuit example 2017-01-11 16:23:49 -07:00
Tanner Linsley dd433f7d9c 3.2.1 2017-01-09 13:44:46 -07:00
Tanner Linsley 0daffaf08d Fixed paginationComponent and paginationClassName
Fixes #24 and fixes #25
2017-01-09 13:44:43 -07:00
63 changed files with 14879 additions and 5054 deletions
+77
View File
@@ -0,0 +1,77 @@
module.exports = {
parserOptions: {
ecmaVersion: 8,
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
node: false,
classes: true
},
sourceType: 'module'
},
parser: 'babel-eslint',
extends: ['standard'],
plugins: ['react'],
rules: {
// Nozzle
'jsx-quotes': [2, 'prefer-single'],
'comma-dangle': [2, 'always-multiline'],
// // React
'react/jsx-boolean-value': 2,
'react/jsx-curly-spacing': [2, 'never'],
'react/jsx-equals-spacing': [2, 'never'],
// 'react/jsx-indent': 2,
'react/jsx-indent-props': [2, 2],
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-undef': 2,
'react/jsx-tag-spacing': [
2,
{
closingSlash: 'never',
beforeSelfClosing: 'always',
afterOpening: 'never'
}
],
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'react/self-closing-comp': 2,
'react/jsx-no-bind': [
2,
{
allowArrowFunctions: true,
allowBind: false,
ignoreRefs: true
}
],
'react/no-did-update-set-state': 2,
'react/no-unknown-property': 2,
'react/react-in-jsx-scope': 2,
'react/jsx-closing-bracket-location': [0, 'tag-aligned'],
'react/jsx-tag-spacing': [2, { beforeSelfClosing: 'always' }],
'react/jsx-wrap-multilines': 2,
'react/self-closing-comp': 2,
'react/jsx-key': 2,
'react/jsx-no-comment-textnodes': 2,
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-target-blank': 2,
'react/jsx-no-undef': 2,
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'react/no-danger-with-children': 2,
'react/no-deprecated': 2,
'react/no-direct-mutation-state': 2,
'react/no-find-dom-node': 2,
'react/no-is-mounted': 2,
'react/no-render-return-value': 2,
'react/no-string-refs': 2,
'react/no-unknown-property': 2,
'react/react-in-jsx-scope': 2,
'react/require-render-return': 2
// 'react/jsx-max-props-per-line': [2, { maximum: 1 }]
}
}
+3 -1
View File
@@ -1,6 +1,8 @@
node_modules/
lib/
docs/build
react-table.js
react-table.css
*.log
example/dist/
.idea
.DS_Store
+57
View File
@@ -0,0 +1,57 @@
## 6.5.0
##### New Features
- `column.filterAll` - defaults to `false`, but when set to `true` will provide the entire array of rows to `filterMethod` as opposed to one row at a time. This allows for more fine-grained filtering using any method you can dream up. See the [Custom Filtering example](https://react-table.js.org/#/story/custom-filtering) for more info.
## 6.4.0
##### New Features
- `PadRowComponent` - the content rendered inside of a padding row. Defaults to a react component that renders ` `
## 6.3.0
##### New Features
- `defaultSortDesc` - allows you to set the default sorting direction for all columns to descending.
- `column.defaultSortDesc` - allows you to set the default sorting direction for a specific column. Falls back to the global `defaultSortDesc` when not set at all.
## 6.0.0
##### New Features
- New Renderers:
- `Aggregated` - Custom renderer for aggregated cells
- `Pivot` - Custom renderer for Pivoted Cells (utilizes `Expander` and `PivotValue`)
- `PivotValue` - Custom renderer for Pivot cell values (deprecates the undocumented `pivotRender` option)
- `Expander` - Custom renderer for Pivot cell Expander
- Added custom sorting methods per table via `defaultSortMethod` and per column via `column.sortMethod`
- Pivot columns are now visibly separate and sorted/filtered independently.
- Added `column.resizable` to override global table `resizable` option for specific columns.
- Added `column.sortable` to override global table `sortable` option for specific columns.
- Added `column.filterable` to override global table `filterable` option for specific columns.
- Added `defaultExpanded` table option.
- All callbacks can now be utilized without needing to hoist and manage the piece of state they export. That is what their prop counterparts are for, so now the corresponding prop is used instead of the callback to detect a "fully controlled" state.
- Prevent transitions while column resizing for a smoother resize effect.
- Disable text selection while resizing columns.
##### Breaking API Changes
- New Renderers:
- `Cell` - deprecates and replaces `render`
- `Header` - deprecates and replaces `header`
- `Footer` - deprecates and replaces `footer`
- `Filter`- deprecates and replaces `filterRender`
- Callbacks now provide the destination state as the primary parameter(s). This makes hoisting and controlling the state in redux or component state much easier. eg.
- `onSorting` no longer requires you to build your own toggle logic
- `onResize` no longer requires you to build your own resize logic
- Renamed `onChange` callback -> `onFetchData` which will always fire when a new data model needs to be fetched (or if not using `manual`, when new data is materialized internally).
- Renamed `filtering` -> `filtered`
- Renamed `sorting` -> `sorted`
- Renamed `expandedRows` -> `expanded`
- Renamed `resizing` -> `resized`
- Renamed `defaultResizing` -> `defaultResized`
- Renamed `defaultFiltering` -> `defaultFiltered`
- Renamed `defaultSorting` -> `defaultSorted`
- Renamed `onSortingChange` -> `onSortedChange`
- Renamed `onFilteringChange` -> `onFilteredChange`
- Renamed `onResize` -> `onResizedChange`
- Renamed `onExpandRow` -> `onExpandedChange`
- Renamed `showFilters` -> `filterable`
- Renamed `hideFilter` -> `filterable` (Column option. Note the true/false value is now flipped.)
- `cellInfo.row` and `rowInfo.row` now reference the materialize data for the table. To reference the original row, use `cellInfo.original` and `rowInfo.original`
- Removed `pivotRender` column option. You can now control how the value is displayed by overriding the `PivotValueComponent` or the individual column's `PivotValue` renderer. See [Pivoting Options Story](https://react-table.js.org/?selectedKind=2.%20Demos&selectedStory=Pivoting%20Options&full=0&down=1&left=1&panelRight=0&downPanel=kadirahq%2Fstorybook-addon-actions%2Factions-panel) for a reference on how to customize pivot column rendering.
+15
View File
@@ -0,0 +1,15 @@
## Problem Description
include a detailed explanation of the problem here...
## Code Snippet(s) or Codepen (http://codepen.io/tannerlinsley/pen/QpeZBa?editors=0010)
## Steps to Reproduce
1. list the steps
2. to reproduce the issue
## System Information
* **Browser & Browser Version:**
* **Node Version:**
* **OS Version:**
* **NPM Version:**
* **Yarn Version:**
+775 -146
View File
File diff suppressed because it is too large Load Diff
+77
View File
@@ -0,0 +1,77 @@
module.exports = {
parserOptions: {
ecmaVersion: 8,
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
node: false,
classes: true
},
sourceType: 'module'
},
parser: 'babel-eslint',
extends: ['standard'],
plugins: ['react'],
rules: {
// Nozzle
'jsx-quotes': [2, 'prefer-single'],
'comma-dangle': [2, 'always-multiline'],
// // React
'react/jsx-boolean-value': 2,
'react/jsx-curly-spacing': [2, 'never'],
'react/jsx-equals-spacing': [2, 'never'],
// 'react/jsx-indent': 2,
'react/jsx-indent-props': [2, 2],
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-undef': 2,
'react/jsx-tag-spacing': [
2,
{
closingSlash: 'never',
beforeSelfClosing: 'always',
afterOpening: 'never'
}
],
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'react/self-closing-comp': 2,
'react/jsx-no-bind': [
2,
{
allowArrowFunctions: true,
allowBind: false,
ignoreRefs: true
}
],
'react/no-did-update-set-state': 2,
'react/no-unknown-property': 2,
'react/react-in-jsx-scope': 2,
'react/jsx-closing-bracket-location': [0, 'tag-aligned'],
'react/jsx-tag-spacing': [2, { beforeSelfClosing: 'always' }],
'react/jsx-wrap-multilines': 2,
'react/self-closing-comp': 2,
'react/jsx-key': 2,
'react/jsx-no-comment-textnodes': 2,
'react/jsx-no-duplicate-props': 2,
'react/jsx-no-target-blank': 2,
'react/jsx-no-undef': 2,
'react/jsx-uses-react': 2,
'react/jsx-uses-vars': 2,
'react/no-danger-with-children': 2,
'react/no-deprecated': 2,
'react/no-direct-mutation-state': 2,
'react/no-find-dom-node': 2,
'react/no-is-mounted': 2,
'react/no-render-return-value': 2,
'react/no-string-refs': 2,
'react/no-unknown-property': 2,
'react/react-in-jsx-scope': 2,
'react/require-render-return': 2
// 'react/jsx-max-props-per-line': [2, { maximum: 1 }]
}
}
+1623
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
{
"name": "new",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "0.9.5",
"standard": "^10.0.2"
},
"dependencies": {
"github-markdown-css": "^2.6.0",
"marked": "^0.3.6",
"namor": "^1.0.1",
"raw-loader": "^0.5.1",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-json-tree": "^0.10.9",
"react-story": "^0.0.10"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+31
View File
@@ -0,0 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tag above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React Table - A lightweight, fast and extendable datagrid built for React</title>
</head>
<body>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start`.
To create a production bundle, use `npm run build`.
-->
</body>
</html>
+110
View File
@@ -0,0 +1,110 @@
import React from 'react'
//
import ReactStory, { defaultProps } from 'react-story'
import './stories/utils/prism.css'
import '../../react-table.css'
import Readme from './stories/Readme.js'
import Simple from './stories/Simple.js'
import CellRenderers from './stories/CellRenderers.js'
import DefaultSorting from './stories/DefaultSorting.js'
import CustomSorting from './stories/CustomSorting.js'
import CustomWidths from './stories/CustomWidths.js'
import CustomComponentProps from './stories/CustomComponentProps.js'
import ServerSide from './stories/ServerSide.js'
import SubComponents from './stories/SubComponents.js'
import Pivoting from './stories/Pivoting.js'
import PivotingSubComponents from './stories/PivotingSubComponents.js'
import OneHundredKRows from './stories/OneHundredKRows.js'
import FunctionalRendering from './stories/FunctionalRendering.js'
import CustomExpanderPosition from './stories/CustomExpanderPosition.js'
import NoDataText from './stories/NoDataText.js'
import Footers from './stories/Footers.js'
import Filtering from './stories/Filtering.js'
import ControlledTable from './stories/ControlledTable.js'
import PivotingOptions from './stories/PivotingOptions.js'
import EditableTable from './stories/EditableTable.js'
import FixedHeader from './stories/FixedHeader.js'
import MultiplePagers from './stories/MultiplePagers';
export default class App extends React.Component {
render() {
return (
<ReactStory
style={{
display: 'block',
width: '100%',
height: '100%'
}}
pathPrefix="story/"
StoryWrapper={props => (
<defaultProps.StoryWrapper
css={{
padding: 0
}}
>
<a
href="//github.com/tannerlinsley/react-table"
style={{
display: 'block',
textAlign: 'center',
borderBottom: 'solid 3px #cccccc'
}}
>
<img
src="//npmcdn.com/react-table/media/Banner.png"
alt="React Table Logo"
style={{
width: '100px'
}}
/>
</a>
<div
{...props}
style={{
padding: '10px'
}}
/>
</defaultProps.StoryWrapper>
)}
stories={[
{ name: 'Readme', component: Readme },
{ name: 'Simple Table', component: Simple },
{
name: 'Cell Renderers & Custom Components',
component: CellRenderers
},
{ name: 'Default Sorting', component: DefaultSorting },
{ name: 'Custom Sorting', component: CustomSorting },
{ name: 'Custom Column Widths', component: CustomWidths },
{ name: 'Custom Component Props', component: CustomComponentProps },
{ name: 'Server-side Data', component: ServerSide },
{ name: 'Sub Components', component: SubComponents },
{ name: 'Pivoting & Aggregation', component: Pivoting },
{
name: 'Pivoting & Aggregation w/ Sub Components',
component: PivotingSubComponents
},
{
name: '100k Rows w/ Pivoting & Sub Components',
component: OneHundredKRows
},
{ name: 'Pivoting Options', component: PivotingOptions },
{ name: 'Functional Rendering', component: FunctionalRendering },
{
name: 'Custom Expander Position',
component: CustomExpanderPosition
},
{ name: 'Custom "No Data" Text', component: NoDataText },
{ name: 'Footers', component: Footers },
{ name: 'Custom Filtering', component: Filtering },
{ name: 'Controlled Component', component: ControlledTable },
{ name: 'Editable Table', component: EditableTable },
{ name: 'Fixed Header w/ Vertical Scroll', component: FixedHeader },
{ name: 'Multiple Pagers (Top and Bottom)', component: MultiplePagers}
]}
/>
)
}
}
+8
View File
@@ -0,0 +1,8 @@
html, body, #root {
height: 100%
}
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react'
import ReactDOM from 'react-dom'
//
import './index.css'
import App from './App.js'
ReactDOM.render(
<App />,
document.getElementById('root')
)
+109
View File
@@ -0,0 +1,109 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
const statusChance = Math.random()
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
progress: Math.floor(Math.random() * 100),
status: statusChance > 0.66 ? 'relationship'
: statusChance > 0.33 ? 'complicated'
: 'single'
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Profile Progress',
accessor: 'progress',
Cell: row => (
<div
style={{
width: '100%',
height: '100%',
backgroundColor: '#dadada',
borderRadius: '2px'
}}
>
<div
style={{
width: `${row.value}%`,
height: '100%',
backgroundColor: row.value > 66 ? '#85cc00'
: row.value > 33 ? '#ffbf00'
: '#ff2e00',
borderRadius: '2px',
transition: 'all .2s ease-out'
}}
/>
</div>
)
}, {
Header: 'Status',
accessor: 'status',
Cell: row => (
<span>
<span style={{
color: row.value === 'relationship' ? '#ff2e00'
: row.value === 'complicated' ? '#ffbf00'
: '#57d500',
transition: 'all .3s ease'
}}>
&#x25cf;
</span> {
row.value === 'relationship' ? 'In a relationship'
: row.value === 'complicated' ? `It's complicated`
: 'Single'
}
</span>
)
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./CellRenderers')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+101
View File
@@ -0,0 +1,101 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
width: 170
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
function makeDefaultState()
{
return {
sorted: [],
page: 0,
pageSize: 10,
expanded: {},
resized: [],
filtered: []
}
}
class Story extends React.PureComponent {
constructor () {
super()
this.state = makeDefaultState()
this.resetState = this.resetState.bind(this)
}
resetState(){
this.setState(makeDefaultState())
}
render () {
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
pivotBy={['lastName']}
filterable
// Controlled Props
sorted={this.state.sorted}
page={this.state.page}
pageSize={this.state.pageSize}
expanded={this.state.expanded}
resized={this.state.resized}
filtered={this.state.filtered}
// Callbacks
onSortedChange={sorted => this.setState({sorted})}
onPageChange={page => this.setState({page})}
onPageSizeChange={(pageSize, page) => this.setState({page, pageSize})}
onExpandedChange={expanded => this.setState({expanded})}
onResizedChange={resized => this.setState({resized})}
onFilteredChange={filtered => this.setState({filtered})}
/>
</div>
<br />
<div style={{float:'right'}}><button onClick={this.resetState}>Reset State</button></div>
<pre><code><strong>this.state ===</strong> {JSON.stringify(this.state, null, 2)}</code></pre>
<br />
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./ControlledTable')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+76
View File
@@ -0,0 +1,76 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<strong>Hey!</strong> Open your console! :)
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
getTdProps={(state, rowInfo, column, instance) => {
return {
onMouseEnter: e => console.log('Cell - onMouseEnter', {
state,
rowInfo,
column,
instance,
event: e
})
}
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./CustomComponentProps')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
@@ -0,0 +1,81 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({words: 1, numbers: 0}),
lastName: namor.generate({words: 1, numbers: 0}),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
Footer: () => <div style={{textAlign: 'center'}}>First Name</div>
}, {
Header: 'Last Name',
accessor: 'lastName',
Footer: () => <div style={{textAlign: 'center'}}>Last Name</div>
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
Footer: () => <div style={{textAlign: 'center'}}>Age</div>
}]
}, {
Header: 'Expand',
columns: [{
expander: true,
Header: () => (<strong>More</strong>),
width: 65,
Expander: ({isExpanded, ...rest}) => (
<div>
{isExpanded ? <span>&#x2299;</span> : <span>&#x2295;</span>}
</div>
),
style: {cursor: 'pointer', fontSize: 25, padding: '0', textAlign: 'center', userSelect: 'none'},
Footer: () => <span>&hearts;</span>
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
SubComponent={() => <span>Hello</span>}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./CustomExpanderPosition')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+78
View File
@@ -0,0 +1,78 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name (Sorted by Length, A-Z)',
accessor: 'firstName',
sortMethod: (a, b) => {
if (a.length === b.length) {
return a > b ? 1 : -1
}
return a.length > b.length ? 1 : -1
}
}, {
Header: 'Last Name (Sorted in reverse, A-Z)',
id: 'lastName',
accessor: d => d.lastName,
sortMethod: (a, b) => {
if (a === b) {
return 0
}
const aReverse = a.split('').reverse().join('')
const bReverse = b.split('').reverse().join('')
return aReverse > bReverse ? 1 : -1
}
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./CustomSorting')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+67
View File
@@ -0,0 +1,67 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
maxWidth: 200
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
width: 300
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
minWidth: 400
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./CustomWidths')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+68
View File
@@ -0,0 +1,68 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
defaultSorted={[{
id: 'age',
desc: true
}]}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./DefaultSorting')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+70
View File
@@ -0,0 +1,70 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
constructor (props, context) {
super(props, context)
this.renderEditable = this.renderEditable.bind(this)
this.state = {
data: [
{ firstName: 'Lucy', lastName: 'Marks' },
{ firstName: 'Bejamin', lastName: 'Pike' }
]
}
this.columns = [
{
Header: 'First Name',
accessor: 'firstName',
Cell: this.renderEditable
},
{
Header: 'Last Name',
accessor: 'lastName',
Cell: this.renderEditable
},
{
Header: 'Full Name',
id: 'full',
accessor: d => d.firstName + ' ' + d.lastName
}
]
}
renderEditable (cellInfo) {
return (<div style={{ backgroundColor: '#fafafa' }} contentEditable suppressContentEditableWarning onBlur={(e) => {
const data = [...this.state.data]
data[cellInfo.index][cellInfo.column.id] = e.target.textContent
this.setState({data: data})
}}>{this.state.data[cellInfo.index][cellInfo.column.id]}</div>)
}
render () {
return (
<div className='table-wrap' style={{marginBottom: '20px'}}>
<p>First two columns are editable just by clicking into them using the <code>contentEditable</code> attribute. Last column (Full Name) is computed from the first two.</p>
<ReactTable
data={this.state.data}
columns={this.columns}
defaultPageSize={2}
showPageSizeOptions={false}
showPagination={false}
/>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./EditableTable')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+236
View File
@@ -0,0 +1,236 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import matchSorter from 'match-sorter'
import CodeHighlight from './components/codeHighlight'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
constructor(props) {
super(props)
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
this.state = {
tableOptions: {
loading: false,
showPagination: true,
showPageSizeOptions: true,
showPageJump: true,
collapseOnSortingChange: true,
collapseOnPageChange: true,
collapseOnDataChange: true,
freezeWhenExpanded: false,
filterable: true,
sortable: true,
resizable: true
},
data: data
}
this.setTableOption = this.setTableOption.bind(this)
}
render() {
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName',
filterMethod: (filter, row) =>
row[filter.id].startsWith(filter.value) &&
row[filter.id].endsWith(filter.value)
},
{
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
filterMethod: (filter, rows) =>
matchSorter(rows, filter.value, { keys: ['lastName'] }),
filterAll: true
}
]
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age'
},
{
Header: 'Over 21',
accessor: 'age',
id: 'over',
Cell: ({ value }) => (value >= 21 ? 'Yes' : 'No'),
filterMethod: (filter, row) => {
if (filter.value === 'all') {
return true
}
if (filter.value === 'true') {
return row[filter.id] >= 21
}
return row[filter.id] < 21
},
Filter: ({ filter, onChange }) =>
<select
onChange={event => onChange(event.target.value)}
style={{ width: '100%' }}
value={filter ? filter.value : 'all'}
>
<option value="all" />
<option value="true">Can Drink</option>
<option value="false">Can't Drink</option>
</select>
}
]
}
]
return (
<div>
<div>
<h1>Table Options</h1>
<table>
<tbody>
{Object.keys(this.state.tableOptions).map(optionKey => {
const optionValue = this.state.tableOptions[optionKey]
return (
<tr key={optionKey}>
<td>
{optionKey}
</td>
<td style={{ paddingLeft: 10, paddingTop: 5 }}>
<input
type="checkbox"
name={optionKey}
checked={optionValue}
onChange={this.setTableOption}
/>
</td>
</tr>
)
})}
</tbody>
</table>
</div>
<div className="table-wrap">
<ReactTable
className="-striped -highlight"
data={this.state.data}
columns={columns}
defaultPageSize={10}
defaultFilterMethod={(filter, row) =>
String(row[filter.id]) === filter.value}
{...this.state.tableOptions}
SubComponent={row => {
return (
<div style={{ padding: '20px' }}>
<em>
You can put any component you want here, even another React
Table!
</em>
<br />
<br />
<ReactTable
data={this.state.data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={row => {
return (
<div style={{ padding: '20px' }}>
<em>It even has access to the row data: </em>
<CodeHighlight>
{() => JSON.stringify(row, null, 2)}
</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{ textAlign: 'center' }}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<div>
<h1>Custom Filters In This Example</h1>
<p>
The default filter for all columns of a table if it is not specified
in the configuration is set to match on values that start with the
filter text. Example: age.startsWith("2").
</p>
<p>
This example overrides the default filter behavior by setting the{' '}
<strong>defaultFilterMethod</strong> table option to match on values
that are exactly equal to the filter text. Example: age == "23")
</p>
<p>
Each column can also be customized with the column{' '}
<strong>filterMethod</strong> option:
</p>
<p>
In this example the firstName column filters on the value starting
with and ending with the filter value.
</p>
<p>
In this example the lastName column filters using{' '}
<a href="https://github.com/kentcdodds">Kent C. Dodd</a>'s{' '}
<a href="https://github.com/kentcdodds/match-sorter">
match-sorter
</a>{' '}
fuzzy search module. Note that 'filterAll' is set to true, which
allows us to filter using the entire dataset instead of just one row
at a time.
</p>
<p>
To completely override the filter that is shown, you can set the{' '}
<strong>Filter</strong> column option. Using this option you can
specify the JSX that is shown. The option is passed an{' '}
<strong>onChange</strong> method that must be called with the value
that you wan't to pass to the <strong>filterMethod</strong> option
whenever the filter has changed.
</p>
</div>
</div>
)
}
setTableOption(event) {
const target = event.target
const value = target.type === 'checkbox' ? target.checked : target.value
const name = target.name
this.setState({
tableOptions: {
...this.state.tableOptions,
[name]: value
}
})
}
}
// Source Code
const source = require('!raw!./Filtering')
export default () =>
<div>
<Story />
<CodeHighlight>
{() => source}
</CodeHighlight>
</div>
+81
View File
@@ -0,0 +1,81 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render() {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
children: _.map(_.range(10), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
}
})
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName'
},
{
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}
]
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age'
}
]
}
]
return (
<div>
<div className="table-wrap">
<ReactTable
className="-striped -highlight"
data={data}
columns={columns}
defaultPageSize={20}
style={{
height: '400px' // This will force the table body to overflow and scroll, since there is not enough room
}}
/>
</div>
<div style={{ textAlign: 'center' }}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./FixedHeader')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+92
View File
@@ -0,0 +1,92 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
Footer: (
<span><strong>Popular:</strong> {
_.first(
_.reduce(
_.map(
_.groupBy(
data, d => d.firstName
)
),
(a, b) => a.length > b.length ? a : b
)
).firstName}
</span>
)
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
Footer: (
<span><strong>Longest:</strong> {
_.reduce(
_.map(
_.groupBy(
data, d => d.lastName
),
(d, key) => key
),
(a, b) => a.length > b.length ? a : b
)}
</span>
)
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
Footer: <span><strong>Average:</strong> {_.round(_.mean(_.map(data, d => d.age)))}</span>
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./Footers')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+137
View File
@@ -0,0 +1,137 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import JSONTree from 'react-json-tree'
import ReactTable from '../../../lib/index'
const JSONtheme = {
scheme: 'monokai',
author: 'wimer hazenberg (http://www.monokai.nl)',
base00: '#272822',
base01: '#383830',
base02: '#49483e',
base03: '#75715e',
base04: '#a59f85',
base05: '#f8f8f2',
base06: '#f5f4f1',
base07: '#f9f8f5',
base08: '#f92672',
base09: '#fd971f',
base0A: '#f4bf75',
base0B: '#a6e22e',
base0C: '#a1efe4',
base0D: '#66d9ef',
base0E: '#ae81ff',
base0F: '#cc6633'
}
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
Footer: 'Footer'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
Footer: 'Footer'
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
Footer: 'Footer'
}]
}]
return (
<div>
<strong>Functional rendering</strong> simply means that you have all of the building blocks to render your own React Table however you'd like.
<br />
<br />
<br />
<br />
<strong>Decorating the standard table output</strong>
<br />
<br />
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
>
{(state, makeTable, instance) => {
return (
<div style={{
background: '#ffcf00',
borderRadius: '5px',
overflow: 'hidden',
padding: '5px'
}}>
<pre><code>state.allVisibleColumns === {JSON.stringify(state.allVisibleColumns, null, 4)}</code></pre>
{makeTable()}
</div>
)
}}
</ReactTable>
</div>
<br />
<br />
<strong>Need more control? This is the entire table state and component instance at your disposal!</strong>
<br />
<br />
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
>
{(state, StandardTable, instance) => {
return (
<div>
<JSONTree
data={Object.assign({}, state, {children: 'function () {...}'})}
theme={JSONtheme}
invertTheme
/>
</div>
)
}}
</ReactTable>
</div>
<br />
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./FunctionalRendering')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+73
View File
@@ -0,0 +1,73 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
children: _.map(_.range(10), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
showPagination
showPaginationTop
showPaginationBottom
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./MultiplePagers')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+57
View File
@@ -0,0 +1,57 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={[]}
noDataText='Oh Noes!'
// noDataText={() => 'Oh Noes!'} // Supports functions
// noDataText={() => <span>Oh Noes!</span>} // Supports JSX / React Components
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./NoDataText')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+97
View File
@@ -0,0 +1,97 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(100000), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
visits: Math.floor(Math.random() * 100)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
Aggregated: row => {
return <span>{row.value} (avg)</span>
}
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals)
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
className='-striped -highlight'
defaultPageSize={10}
pivotBy={['firstName', 'lastName']}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./OneHundredKRows')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+74
View File
@@ -0,0 +1,74 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(1000), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
visits: Math.floor(Math.random() * 100)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
Aggregated: row => {
return <span>{row.value} (avg)</span>
}
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals)
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
className='-striped -highlight'
defaultPageSize={10}
pivotBy={['firstName', 'lastName']}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./Pivoting')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+132
View File
@@ -0,0 +1,132 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(1000), d => {
return {
firstName: namor.generate({words: 1, numbers: 0}),
lastName: namor.generate({words: 1, numbers: 0}),
age: Math.floor(Math.random() * 30),
visits: Math.floor(Math.random() * 100)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
PivotValue: ({value}) => <span style={{color: 'darkred'}}>{value}</span>
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName,
PivotValue: ({value}) => <span style={{color: 'darkblue'}}>{value}</span>,
Footer: () => <div style={{textAlign: 'center'}}><strong>Pivot Column Footer</strong></div>
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
aggregate: vals => {
return _.round(_.mean(vals))
},
Aggregated: row => <span>{row.value} (avg)</span>
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
filterable: false
}]
}, {
pivot: true,
Header: () => <strong>Overridden Pivot Column Header Group</strong>
}, {
expander: true
}]
const subtableColumns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName'
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}, {
Header: 'Visits',
accessor: 'visits'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
defaultSorted={[{id: 'firstName', desc: false}, {id: 'lastName', desc: true}]}
collapseOnSortingChange={false}
filterable
ExpanderComponent={({isExpanded, ...rest}) => (
isExpanded ? <span> &#10136; </span> : <span> &#10137; </span>
)}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={subtableColumns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./PivotingOptions')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+100
View File
@@ -0,0 +1,100 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(1000), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
visits: Math.floor(Math.random() * 100)
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age',
aggregate: vals => _.round(_.mean(vals)),
Aggregated: row => {
return <span>{row.value} (avg)</span>
},
filterMethod: (filter, row) => (filter.value === `${row[filter.id]} (avg)`)
}, {
Header: 'Visits',
accessor: 'visits',
aggregate: vals => _.sum(vals),
filterable: false
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
defaultPageSize={10}
className='-striped -highlight'
pivotBy={['firstName', 'lastName']}
filterable
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./PivotingSubComponents')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+20
View File
@@ -0,0 +1,20 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import marked from 'marked'
//
import Readme from '!raw!../../../README.md'
import 'github-markdown-css/github-markdown.css'
export default class Story extends React.Component {
render() {
return (
<span
className="markdown-body"
dangerouslySetInnerHTML={{ __html: marked(Readme) }}
/>
)
}
componentDidMount() {
global.Prism.highlightAll()
}
}
+121
View File
@@ -0,0 +1,121 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
const rawData = _.map(_.range(3424), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
// Now let's mock the server. It's job is simple: use the table model to sort and return the page data
const requestData = (pageSize, page, sorted, filtered) => {
return new Promise((resolve, reject) => {
// On the server, you'll likely use SQL or noSQL or some other query language to do this.
// For this mock, we'll just use lodash
let filteredData = rawData
if (filtered.length) {
filteredData = filtered.reduce(
(filteredSoFar, nextFilter) => {
return filteredSoFar.filter(
(row) => {
return (row[nextFilter.id] + '').includes(nextFilter.value)
})
}
, filteredData)
}
const sortedData = _.orderBy(filteredData, sorted.map(sort => {
return row => {
if (row[sort.id] === null || row[sort.id] === undefined) {
return -Infinity
}
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id]
}
}), sorted.map(d => d.desc ? 'desc' : 'asc'))
// Be sure to send back the rows to be displayed and any other pertinent information, like how many pages there are total.
const res = {
rows: sortedData.slice(pageSize * page, (pageSize * page) + pageSize),
pages: Math.ceil(filteredData.length / pageSize)
}
// Here we'll simulate a server response with 500ms of delay.
setTimeout(() => resolve(res), 500)
})
}
class Story extends React.PureComponent {
constructor () {
super()
this.state = {
data: [],
pages: null,
loading: true
}
this.fetchData = this.fetchData.bind(this)
}
fetchData (state, instance) {
// Whenever the table model changes, or the user sorts or changes pages, this method gets called and passed the current table model.
// You can set the `loading` prop of the table to true to use the built-in one or show you're own loading bar if you want.
this.setState({loading: true})
// Request the data however you want. Here, we'll use our mocked service we created earlier
requestData(state.pageSize, state.page, state.sorted, state.filtered)
.then((res) => {
// Now just get the rows of data to your React Table (and update anything else like total pages or loading)
this.setState({
data: res.rows,
pages: res.pages,
loading: false
})
})
}
render () {
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
columns={[{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}, {
Header: 'Age',
accessor: 'age'
}]}
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
defaultPageSize={10}
filterable
data={this.state.data} // Set the rows to be displayed
pages={this.state.pages} // Display the total number of pages
loading={this.state.loading} // Display the loading overlay when we need it
onFetchData={this.fetchData} // Request new data when things change
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./ServerSide')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+77
View File
@@ -0,0 +1,77 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render() {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
children: _.map(_.range(10), d => {
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
lastName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30)
}
})
}
})
const columns = [
{
Header: 'Name',
columns: [
{
Header: 'First Name',
accessor: 'firstName'
},
{
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}
]
},
{
Header: 'Info',
columns: [
{
Header: 'Age',
accessor: 'age'
}
]
}
]
return (
<div>
<div className="table-wrap">
<ReactTable
className="-striped -highlight"
data={data}
columns={columns}
defaultPageSize={10}
/>
</div>
<div style={{ textAlign: 'center' }}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./Simple')
export default () =>
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
+146
View File
@@ -0,0 +1,146 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
constructor (props) {
super(props)
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({words: 1, numbers: 0}),
lastName: namor.generate({words: 1, numbers: 0}),
age: Math.floor(Math.random() * 30)
}
})
this.state = {
tableOptions: {
loading: false,
showPagination: true,
showPageSizeOptions: true,
showPageJump: true,
collapseOnSortingChange: true,
collapseOnPageChange: true,
collapseOnDataChange: true,
freezeWhenExpanded: false,
filterable: false,
sortable: true,
resizable: true
},
data: data
}
this.setTableOption = this.setTableOption.bind(this)
}
render () {
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName'
}, {
Header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div>
<h1>Table Options</h1>
<table>
<tbody>
{
Object.keys(this.state.tableOptions).map(optionKey => {
const optionValue = this.state.tableOptions[optionKey]
return (
<tr key={optionKey}>
<td>{optionKey}</td>
<td style={{paddingLeft: 10, paddingTop: 5}}>
<input type='checkbox'
name={optionKey}
checked={optionValue}
onChange={this.setTableOption}
/>
</td>
</tr>
)
})
}
</tbody>
</table>
</div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={this.state.data}
columns={columns}
defaultPageSize={10}
{...this.state.tableOptions}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>You can put any component you want here, even another React Table!</em>
<br />
<br />
<ReactTable
data={this.state.data}
columns={columns}
defaultPageSize={3}
showPagination={false}
SubComponent={(row) => {
return (
<div style={{padding: '20px'}}>
<em>It even has access to the row data: </em>
<CodeHighlight>{() => JSON.stringify(row, null, 2)}</CodeHighlight>
</div>
)
}}
/>
</div>
)
}}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
setTableOption (event) {
const target = event.target
const value = target.type === 'checkbox' ? target.checked : target.value
const name = target.name
this.setState({
tableOptions: {
...this.state.tableOptions,
[name]: value
}
})
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./SubComponents')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
+78
View File
@@ -0,0 +1,78 @@
/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react'
import _ from 'lodash'
import namor from 'namor'
import ReactTable from '../../../lib/index'
class Story extends React.PureComponent {
render () {
const data = _.map(_.range(5553), d => {
const children = _.map(_.range(10), d => {
const grandChildren = _.map(_.range(10), d => {
return {
age: Math.floor(Math.random() * 30)
}
})
return {
firstName: namor.generate({ words: 1, numbers: 0 }),
age: Math.floor(Math.random() * 30),
children: grandChildren
}
})
return {
lastName: namor.generate({ words: 1, numbers: 0 }),
firstName: children.map(d => d.firstName),
age: Math.floor(Math.random() * 30),
children
}
})
const columns = [{
Header: 'Name',
columns: [{
Header: 'First Name',
accessor: 'firstName',
expander: true
}, {
Header: 'Last Name',
accessor: 'lastName'
}]
}, {
Header: 'Info',
columns: [{
Header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
className='-striped -highlight'
data={data}
columns={columns}
defaultPageSize={10}
subRowsKey='children'
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
</div>
)
}
}
// Source Code
const CodeHighlight = require('./components/codeHighlight').default
const source = require('!raw!./SubRows')
export default () => (
<div>
<Story />
<CodeHighlight>{() => source}</CodeHighlight>
</div>
)
@@ -0,0 +1,21 @@
import React from 'react'
import '../utils/prism'
export default class CodeHighlight extends React.Component {
render () {
const { language, children } = this.props
return (
<pre>
<code className={'language-' + (language || 'jsx')}>
{children()}
</code>
</pre>
)
}
componentDidMount () {
window.Prism.highlightAll()
}
componentDidUpdate () {
window.Prism.highlightAll()
}
}
+138
View File
@@ -0,0 +1,138 @@
/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #a67f59;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
File diff suppressed because one or more lines are too long
+5783
View File
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1 +0,0 @@
# Jumpsuit Getting Started
-28
View File
@@ -1,28 +0,0 @@
var fs = require('fs')
var path = require('path')
var stylus = require('stylus')
var nib = require('nib')
var stylusEntry = path.resolve('src/app.styl')
module.exports = {
styles: {
extensions: ['.css', '.styl'],
action: buildStyles
}
}
function buildStyles () {
return new Promise(function (resolve, reject) {
stylus.render(fs.readFileSync(stylusEntry, 'utf8'), {
'include css': true,
'hoist atrules': true,
compress: process.env.NODE_ENV === 'production',
paths: [path.resolve('src')],
use: nib()
}, function (err, css) {
if (err) reject(err)
else resolve(css)
})
})
}
-28
View File
@@ -1,28 +0,0 @@
{
"name": "react-table-example",
"version": "0.0.1",
"description": "Jumpsuit getting started example",
"license": "MIT",
"private": true,
"repository": {
"type": "git",
"url": "git+https://github.com/jumpsuit/jumpsuit.git"
},
"scripts": {
"watch": "jumpsuit watch",
"build": "jumpsuit build",
"deploy": "jumpsuit build && zab deploy"
},
"devDependencies": {
"nib": "^1.1.0",
"standard": "^8.4.0",
"stylus": "^0.54.5"
},
"dependencies": {
"jumpsuit": "^1.3.3",
"lodash": "^4.16.4",
"namor": "^0.3.0",
"react-syntax-highlighter": "^3.0.0",
"react-table": "^3.1.2"
}
}
-17
View File
@@ -1,17 +0,0 @@
import { Render, Router, Route, IndexRoute } from 'jumpsuit'
//
import Layout from 'components/layout'
import Simple from 'screens/simple'
import ServerSide from 'screens/serverSide'
Render(null, (
<Router>
<Route path='/' component={Layout}>
<IndexRoute component={Simple} />
<Route path='simple' component={Simple} />
<Route path='server-side' component={ServerSide} />
</Route>
</Router>
), {
useHash: false
})
-112
View File
@@ -1,112 +0,0 @@
// -----------------------------------------------------------------------------
// Globals
// -----------------------------------------------------------------------------
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,600')
@import 'nib'
global-reset()
// -----------------------------------------------------------------------------
// vendor styles
// -----------------------------------------------------------------------------
@import '../node_modules/react-table/src/index'
// -----------------------------------------------------------------------------
// variables
// -----------------------------------------------------------------------------
$fnt-open-sans = 'Open Sans', sans-serif
$react = #25d8fd
// -----------------------------------------------------------------------------
// styles
// -----------------------------------------------------------------------------
*
box-sizing border-box
html
min-height 100vh
body
background: white
font-family: $fnt-open-sans
font-weight: 300
h1
font-size: 2.5em
color: white
a
color: darken($react, 20%)
font-weight: bold
text-decoration: none
strong
font-weight: bold
.logo
width: 400px
max-width: 100%
.container
display: flex
flex-direction: column
align-items: center
justify-content: center
min-height: 100vh
padding-top: 20px
.github-addon
font-size: 20px
padding: 10px
.viewport
width:100%
.table-wrap
width: 90%
margin: auto
padding: 10px
border-radius: 5px
box-shadow: 0 0 20px 0 alpha(black, .2)
.menu
display:block
margin: 0 10px 20px
ul
display:block
li
display:inline-block
a
display:block
padding: 10px
margin: 5px
background: alpha(black, .4)
color: white
border-radius: 3px
transition: all .2s ease-out
&.active
&:hover
background: alpha(black, .9)
.ReactTable
thead
th
td
&.-sort-asc
box-shadow:inset 0 3px 0 0 alpha(black, .6)
&.-sort-desc
box-shadow:inset 0 -3px 0 0 alpha(black, .6)
pre
display:block
font-family: monospace
font-size: 15px
line-height: 20px
border-radius: 5px
margin: 20px auto
max-width: 90%
padding: 0 20px !important
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

-14
View File
@@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React-Table Demo</title>
<link rel="stylesheet" href="/app.css" charset="utf-8">
</head>
<body>
<div id="app"></div>
<script src="/app.js"></script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>
-11
View File
@@ -1,11 +0,0 @@
import { Component } from 'jumpsuit'
import SyntaxHighlighter from 'react-syntax-highlighter'
import atomOneDark from '../../node_modules/react-syntax-highlighter/dist/styles/atom-one-dark'
export default Component({
render () {
return (
<SyntaxHighlighter language='javascript' style={atomOneDark}>{this.props.children}</SyntaxHighlighter>
)
}
})
-59
View File
@@ -1,59 +0,0 @@
import { Component, Link } from 'jumpsuit'
export default Component({
render () {
return (
<div className='container'>
<div style={{textAlign: 'center'}}>
<h1>
<span style={{position: 'absolute', textIndent: '-9999em'}}>
react-table
</span>
<img src='/Banner.png' className='logo' />
</h1>
<br />
<div>
<a
className='github-button'
href='https://github.com/tannerlinsley/react-table'
target='_blank'
data-style='mega'
data-count-href='/tannerlinsley/react-table/stargazers'
data-count-api='/repos/tannerlinsley/react-table#stargazers_count'
data-count-aria-label='# stargazers on GitHub'
aria-label='Star tannerlinsley/react-table on GitHub'>
Star
</a>
</div>
<br />
<div className='github-addon'>
<a
target='_blank'
href='https://github.com/tannerlinsley/react-table'>
View on Github
</a>
</div>
<br />
<br />
</div>
<div className='menu'>
<ul>
<li>
<Link to='/simple' activeClassName='active'>
Simple
</Link>
</li>
<li>
<Link to='/server-side' activeClassName='active'>
Server-Side
</Link>
</li>
</ul>
</div>
<div className='viewport'>
{this.props.children}
</div>
</div>
)
}
})
-171
View File
@@ -1,171 +0,0 @@
import { Component } from 'jumpsuit'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from 'components/codeHighlight'
import ReactTable from 'react-table'
// Let's mock some data to play around with
const rawData = _.map(_.range(3424), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
// Now let's mock the server. It's job is simple: use the table model to sort and return the page data
const requestData = (pageSize, page, sorting) => {
return new Promise((resolve, reject) => {
// On the server, you'll likely use SQL or noSQL or some other query language to do this.
// For this mock, we'll just use lodash
const sortedData = _.orderBy(rawData, sorting.map(sort => {
return row => {
if (row[sort.id] === null || row[sort.id] === undefined) {
return -Infinity
}
return typeof row[sort.id] === 'string' ? row[sort.id].toLowerCase() : row[sort.id]
}
}), sorting.map(d => d.asc ? 'asc' : 'desc'))
// Be sure to send back the rows to be displayed and any other pertinent information, like how many pages there are total.
const res = {
rows: sortedData.slice(pageSize * page, (pageSize * page) + pageSize),
pages: Math.ceil(rawData.length / pageSize)
}
// Here we'll simulate a server response with 500ms of delay.
setTimeout(() => resolve(res), 500)
})
}
export default Component({
getInitialState () {
// To handle our data server-side, we need a few things in the state to help us out:
return {
data: [],
pages: null,
loading: true
}
},
fetchData (state, instance) {
// Whenever the table model changes, or the user sorts or changes pages, this method gets called and passed the current table model.
// You can set the `loading` prop of the table to true to use the built-in one or show you're own loading bar if you want.
this.setState({loading: true})
// Request the data however you want. Here, we'll use our mocked service we created earlier
requestData(state.pageSize, state.page, state.sorting)
.then((res) => {
// Now just get the rows of data to your React Table (and update anything else like total pages or loading)
this.setState({
data: res.rows,
pages: res.pages,
loading: false
})
})
},
render () {
return (
<div>
<div className='table-wrap'>
<ReactTable
columns={[{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]}
manual // Forces table not to paginate or sort automatically, so we can handle it server-side
pageSize={10}
data={this.state.data} // Set the rows to be displayed
pages={this.state.pages} // Display the total number of pages
loading={this.state.loading} // Display the loading overlay when we need it
onChange={this.fetchData} // Request new data when things change
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{getCode()}</CodeHighlight>
</div>
)
}
})
function getCode () {
return `
import ReactTable from 'react-table'
import Axios from 'axios'
export default React.creatClass({
getInitialState () {
// To handle our data server-side, we need to keep track of our table state
return {
data: [],
pages: null,
loading: true
}
},
fetchData (state, instance) {
// Whenever the table model changes (sorting, pagination, etc), this method gets called and passed the current table model.
// You can set the 'loading' prop of the table to true to use the built-in loading notice, or show you're own loading bar if you want.
this.setState({loading: true})
// Request the data from a server however you want! Be sure to send the bits of the table model that it may neeed.
Axios.post('mysite.com/data', {
pageSize: state.pageSize,
page: state.page,
sorting: state.sorting
})
.then((res) => {
// Now update your state!
this.setState({
data: res.rows,
pages: res.pages,
loading: false
})
})
},
render () {
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return (
<ReactTable
columns={columns}
manual // This forces table not to paginate or sort automatically, so we can handle things server-side
data={this.state.data} // Set the rows to be displayed
pages={this.state.pages} // Display the total number of pages
loading={this.state.loading} // Display the loading overlay when we need it
onChange={this.fetchData} // Request new data when things change
/>
)
}
})
`
}
-103
View File
@@ -1,103 +0,0 @@
import { Component } from 'jumpsuit'
import _ from 'lodash'
import namor from 'namor'
import CodeHighlight from 'components/codeHighlight'
import ReactTable from 'react-table'
export default Component({
render () {
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
return (
<div>
<div className='table-wrap'>
<ReactTable
data={data}
columns={columns}
pageSize={10}
/>
</div>
<div style={{textAlign: 'center'}}>
<br />
<em>Tip: Hold shift when sorting to multi-sort!</em>
</div>
<CodeHighlight>{getCode()}</CodeHighlight>
</div>
)
}
})
function getCode () {
return `
import ReactTable from 'react-table'
// To help us mock some data
import namor from 'namor'
import _ from 'lodash'
export default () => {
// Mock some data
const data = _.map(_.range(5553), d => {
return {
firstName: namor.generate({ words: 1, numLen: 0 }),
lastName: namor.generate({ words: 1, numLen: 0 }),
age: Math.floor(Math.random() * 30)
}
})
// Create some column definitions
const columns = [{
header: 'Name',
columns: [{
header: 'First Name',
accessor: 'firstName'
}, {
header: 'Last Name',
id: 'lastName',
accessor: d => d.lastName
}]
}, {
header: 'Info',
columns: [{
header: 'Age',
accessor: 'age'
}]
}]
// Display your table!
return (
<ReactTable
data={data}
columns={columns}
pageSize={10}
/>
)
})
`
}
-2741
View File
File diff suppressed because it is too large Load Diff
-8
View File
@@ -1,8 +0,0 @@
{
"name": "react-table",
"root": "dist",
"routes": [{
"src": "/**",
"dest": "index.html"
}]
}
+23 -25
View File
@@ -1,6 +1,6 @@
{
"name": "react-table",
"version": "3.2.0",
"version": "6.5.2",
"description": "A fast, lightweight, opinionated table and datagrid built on React",
"license": "MIT",
"homepage": "https://github.com/tannerlinsley/react-table#readme",
@@ -24,12 +24,18 @@
],
"scripts": {
"build:node": "babel src --out-dir lib --source-maps inline",
"build:css": "rm -rf react-table.css && stylus src/index.styl --use ./node_modules/nib/lib/nib.js --compress -o react-table.css",
"watch": "onchange 'src/**' -i -- npm-run-all build:*",
"test": "standard",
"umd": "rm -rf react-table.js && browserify lib/index.js -s reactTable -x react -t babelify -g uglifyify -o react-table.js",
"prepublish": "npm-run-all build:* && npm run umd",
"postpublish": "git push --tags"
"build:css": "rimraf react-table.css && stylus src/index.styl --compress -o react-table.css && yarn run css:autoprefix",
"css:autoprefix": "postcss --use autoprefixer react-table.css -r",
"watch": "npm-run-all --parallel watch:*",
"watch:node": "onchange 'src/**/*.js' -i -- npm run build:node",
"watch:css": "onchange 'src/**/*.styl' -i -- npm run build:css",
"test": "eslint src",
"umd": "rimraf react-table.js && webpack --config umd.webpack.js",
"build": "npm-run-all build:*",
"prepublish": "npm run build && npm run umd",
"postpublish": "git push --tags",
"docs": "yarn watch & cd docs && yarn && yarn start",
"docs:build": "yarn build && cd docs && yarn && yarn run build"
},
"dependencies": {
"classnames": "^2.2.5"
@@ -38,32 +44,24 @@
"react": "^15.x.x"
},
"devDependencies": {
"autoprefixer": "^6.7.0",
"babel-cli": "6.14.0",
"babel-eslint": "6.1.2",
"babel-preset-es2015": "6.14.0",
"babel-preset-react": "6.11.1",
"babel-preset-stage-2": "6.13.0",
"babelify": "^7.3.0",
"browserify": "13.1.0",
"nib": "^1.1.2",
"eslint": "^4.1.1",
"match-sorter": "^1.8.0",
"npm-run-all": "^3.1.1",
"onchange": "^3.0.2",
"standard": "^8.0.0",
"postcss-cli": "^2.6.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-json-tree": "^0.10.9",
"rimraf": "^2.6.1",
"standard": "^10.0.2",
"stylus": "^0.54.5",
"uglifyify": "3.0.3"
},
"browserify-shim": {
"react": "global:React"
},
"standard": {
"parser": "babel-eslint",
"ignore": [
"node_modules",
"dist",
"lib",
"example",
"react-table.js"
]
"webpack": "^2.5.1"
},
"babel": {
"presets": [
+243
View File
@@ -0,0 +1,243 @@
import React from 'react'
import classnames from 'classnames'
//
import _ from './utils'
import Pagination from './pagination'
const emptyObj = () => ({})
export default {
// General
data: [],
loading: false,
showPagination: true,
showPaginationTop: false,
showPaginationBottom: true,
showPageSizeOptions: true,
pageSizeOptions: [5, 10, 20, 25, 50, 100],
defaultPageSize: 20,
showPageJump: true,
collapseOnSortingChange: true,
collapseOnPageChange: true,
collapseOnDataChange: true,
freezeWhenExpanded: false,
sortable: true,
resizable: true,
filterable: false,
defaultSortDesc: false,
defaultSorted: [],
defaultFiltered: [],
defaultResized: [],
defaultExpanded: {},
defaultFilterMethod: (filter, row, column) => {
const id = filter.pivotId || filter.id
return row[id] !== undefined
? String(row[id]).startsWith(filter.value)
: true
},
defaultSortMethod: (a, b) => {
// force null and undefined to the bottom
a = a === null || a === undefined ? '' : a
b = b === null || b === undefined ? '' : b
// force any string values to lowercase
a = typeof a === 'string' ? a.toLowerCase() : a
b = typeof b === 'string' ? b.toLowerCase() : b
// Return either 1 or -1 to indicate a sort priority
if (a > b) {
return 1
}
if (a < b) {
return -1
}
// returning 0, undefined or any falsey value will use subsequent sorts or the index as a tiebreaker
return 0
},
// Controlled State Props
// page: undefined,
// pageSize: undefined,
// sorted: [],
// filtered: [],
// resized: [],
// expanded: {},
// Controlled State Callbacks
onPageChange: undefined,
onPageSizeChange: undefined,
onSortedChange: undefined,
onFilteredChange: undefined,
onResizedChange: undefined,
onExpandedChange: undefined,
// Pivoting
pivotBy: undefined,
// Key Constants
pivotValKey: '_pivotVal',
pivotIDKey: '_pivotID',
subRowsKey: '_subRows',
aggregatedKey: '_aggregated',
nestingLevelKey: '_nestingLevel',
originalKey: '_original',
indexKey: '_index',
groupedByPivotKey: '_groupedByPivot',
// Server-side Callbacks
onFetchData: () => null,
// Classes
className: '',
style: {},
// Component decorators
getProps: emptyObj,
getTableProps: emptyObj,
getTheadGroupProps: emptyObj,
getTheadGroupTrProps: emptyObj,
getTheadGroupThProps: emptyObj,
getTheadProps: emptyObj,
getTheadTrProps: emptyObj,
getTheadThProps: emptyObj,
getTheadFilterProps: emptyObj,
getTheadFilterTrProps: emptyObj,
getTheadFilterThProps: emptyObj,
getTbodyProps: emptyObj,
getTrGroupProps: emptyObj,
getTrProps: emptyObj,
getTdProps: emptyObj,
getTfootProps: emptyObj,
getTfootTrProps: emptyObj,
getTfootTdProps: emptyObj,
getPaginationProps: emptyObj,
getLoadingProps: emptyObj,
getNoDataProps: emptyObj,
getResizerProps: emptyObj,
// Global Column Defaults
column: {
// Renderers
Cell: undefined,
Header: undefined,
Footer: undefined,
Aggregated: undefined,
Pivot: undefined,
PivotValue: undefined,
Expander: undefined,
Filter: undefined,
// All Columns
sortable: undefined, // use table default
resizable: undefined, // use table default
filterable: undefined, // use table default
show: true,
minWidth: 100,
// Cells only
className: '',
style: {},
getProps: emptyObj,
// Pivot only
aggregate: undefined,
// Headers only
headerClassName: '',
headerStyle: {},
getHeaderProps: emptyObj,
// Footers only
footerClassName: '',
footerStyle: {},
getFooterProps: emptyObj,
filterMethod: undefined,
filterAll: false,
sortMethod: undefined,
},
// Global Expander Column Defaults
expanderDefaults: {
sortable: false,
resizable: false,
filterable: false,
width: 35,
},
pivotDefaults: {
// extend the defaults for pivoted columns here
},
// Text
previousText: 'Previous',
nextText: 'Next',
loadingText: 'Loading...',
noDataText: 'No rows found',
pageText: 'Page',
ofText: 'of',
rowsText: 'rows',
// Components
TableComponent: _.makeTemplateComponent('rt-table', 'Table'),
TheadComponent: _.makeTemplateComponent('rt-thead', 'Thead'),
TbodyComponent: _.makeTemplateComponent('rt-tbody', 'Tbody'),
TrGroupComponent: _.makeTemplateComponent('rt-tr-group', 'TrGroup'),
TrComponent: _.makeTemplateComponent('rt-tr', 'Tr'),
ThComponent: ({ toggleSort, className, children, ...rest }) => {
return (
<div
className={classnames(className, 'rt-th')}
onClick={e => {
toggleSort && toggleSort(e)
}}
{...rest}
>
{children}
</div>
)
},
TdComponent: _.makeTemplateComponent('rt-td', 'Td'),
TfootComponent: _.makeTemplateComponent('rt-tfoot', 'Tfoot'),
FilterComponent: ({ filter, onChange }) =>
<input
type='text'
style={{
width: '100%',
}}
value={filter ? filter.value : ''}
onChange={event => onChange(event.target.value)}
/>,
ExpanderComponent: ({ isExpanded }) =>
<div className={classnames('rt-expander', isExpanded && '-open')}>
&bull;
</div>,
PivotValueComponent: ({ subRows, value }) =>
<span>
{value} {subRows && `(${subRows.length})`}
</span>,
AggregatedComponent: ({ subRows, column }) => {
const previewValues = subRows
.filter(d => typeof d[column.id] !== 'undefined')
.map((row, i) =>
<span key={i}>
{row[column.id]}
{i < subRows.length - 1 ? ', ' : ''}
</span>
)
return (
<span>
{previewValues}
</span>
)
},
PivotComponent: undefined, // this is a computed default generated using
// the ExpanderComponent and PivotValueComponent at run-time in methods.js
PaginationComponent: Pagination,
PreviousComponent: undefined,
NextComponent: undefined,
LoadingComponent: ({ className, loading, loadingText, ...rest }) =>
<div
className={classnames('-loading', { '-active': loading }, className)}
{...rest}
>
<div className='-loading-inner'>
{loadingText}
</div>
</div>,
NoDataComponent: _.makeTemplateComponent('rt-noData', 'NoData'),
ResizerComponent: _.makeTemplateComponent('rt-resizer', 'Resizer'),
PadRowComponent: () => <span>&nbsp;</span>,
}
+979 -492
View File
File diff suppressed because it is too large Load Diff
+181 -112
View File
@@ -1,91 +1,53 @@
@import 'nib'
$easeOutQuad = cubic-bezier(0.250, 0.460, 0.450, 0.940)
$easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
$expandSize = 7px
.ReactTable
position:relative
table
display: flex
flex-direction: column
border: 1px solid alpha(black, .1)
*
box-sizing: border-box
.rt-table
flex: 1
display: flex
flex-direction: column
align-items: stretch
width: 100%
border-collapse: collapse
border: 1px solid alpha(black, .1)
display: block
overflow-x: auto
overflow: auto
.-td
.-th
&-inner
white-space: nowrap
text-overflow: ellipsis
padding: 7px 5px
overflow: hidden
z-index:0
transition: .3s ease
transition-property: width, min-width, padding, opacity
th
td
&:hover
.-td
.-th
&-inner
position:relative
overflow:visible
z-index:1
text-shadow:
0 0 1px white,
0 0 2px white,
1px 0 3px white,
1px 0 4px white,
2px 0 5px white,
2px 0 6px white,
3px 0 7px white,
3px 0 8px white,
4px 0 9px white,
4px 0 10px white,
5px 0 11px white,
5px 0 12px white,
6px 0 13px white,
6px 0 14px white,
7px 0 15px white,
7px 0 16px white,
8px 0 17px white,
8px 0 18px white,
9px 0 19px white,
9px 0 20px white
> *
text-shadow: none
&.-hidden
border:0 !important
opacity: 0 !important
.-th-inner
.-td-inner
width: 0 !important
min-width: 0 !important
padding: 0 !important
thead
box-shadow: 0px 5px 20px 0 alpha(black, .1)
z-index: 0
.rt-thead
flex: 1 0 auto
display: flex
flex-direction: column
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
&.-headerGroups
background: alpha(black, .03)
border-bottom: 1px solid alpha(black, .05)
th
td
background: alpha(black, .03)
&.-filters
border-bottom: 1px solid alpha(black, 0.05)
tr
.rt-th
border-right: 1px solid alpha(black, 0.02)
&.-header
box-shadow: 0 2px 15px 0px alpha(black, .15)
.rt-tr
text-align:center
th
td
width: 1%
background: white
font-weight:500
color: $darkColor
.rt-th
.rt-td
padding: 5px 5px
line-height: normal
position: relative
border-right: 1px solid alpha(black, .05)
transition box-shadow .3s $easeOutBack
box-shadow:inset 0 0 0 0 transparent
@@ -95,40 +57,149 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
box-shadow:inset 0 -3px 0 0 alpha(black, .6)
&.-cursor-pointer
cursor: pointer
&:last-child
border-right: 0
tbody
z-index:0
tr
.rt-resizable-header
overflow: visible
&:last-child
overflow: hidden
.rt-resizable-header-content
overflow: hidden
text-overflow: ellipsis
.rt-header-pivot
border-right-color: #f7f7f7
.rt-header-pivot:after, .rt-header-pivot:before
left: 100%
top: 50%
border: solid transparent
content: " "
height: 0
width: 0
position: absolute
pointer-events: none
.rt-header-pivot:after
border-color: rgba(255, 255, 255, 0)
border-left-color: #FFF
border-width: 8px
margin-top: -8px
.rt-header-pivot:before
border-color: rgba(102, 102, 102, 0)
border-left-color: #f7f7f7
border-width: 10px
margin-top: -10px
.rt-tbody
flex: 99999 1 auto
display: flex
flex-direction: column
overflow: auto
// z-index:0
.rt-tr-group
border-bottom: solid 1px alpha(black, .05)
&:last-child
border-bottom: 0
&:first-child td
box-shadow: inset 0 20px 20px -20px alpha(black, .2)
td
.rt-td
border-right:1px solid alpha(black, .02)
&:last-child
border-right:0
.rt-expandable
cursor: pointer
.rt-tr-group
flex: 1 0 auto
display: flex
flex-direction: column
align-items: stretch
.rt-tr
flex: 1 0 auto
display: inline-flex
.rt-th
.rt-td
flex: 1 0 0px
white-space: nowrap
text-overflow: ellipsis
padding: 7px 5px
overflow: hidden
transition: .3s ease
transition-property: width, min-width, padding, opacity
&.striped
tbody tr:nth-child(even)
&.-hidden
width: 0 !important
min-width: 0 !important
padding: 0 !important
border:0 !important
opacity: 0 !important
.rt-expander
display: inline-block
position:relative
margin: 0
color: transparent
margin: 0 10px
&:after
content: ''
position: absolute
width: 0
height: 0
top:50%
left:50%
transform: translate(-50%, -50%) rotate(-90deg)
border-left: ($expandSize * .72) solid transparent
border-right: ($expandSize * .72) solid transparent
border-top: $expandSize solid alpha(black, .8)
transition: all .3s $easeOutBack
cursor: pointer
&.-open:after
transform: translate(-50%, -50%) rotate(0deg)
.rt-resizer
display: inline-block
position: absolute
width: 36px
top: 0
bottom: 0
right: -18px
cursor: col-resize
z-index: 10
.rt-tfoot
display: flex
flex-direction: column
box-shadow: 0 0px 15px 0px alpha(black, .15)
.rt-td
border-right:1px solid alpha(black, .05)
&:last-child
border-right:0
&.-striped
.rt-tr.-odd
background: alpha(black, .03)
&.highlight
tbody tr:hover
background: alpha(black, .05)
&.-highlight
.rt-tbody
.rt-tr:not(.-padRow):hover
background: alpha(black, .05)
.-pagination
width:100%
z-index: 1
display:flex
justify-content: space-between
align-items: center
align-items: stretch
flex-wrap: wrap
padding-top:3px
padding: 3px
box-shadow: 0 0px 15px 0px alpha(black, .1)
border-top: 2px solid alpha(black, .1)
.-btn
appearance:none
display:block
width:100%
height:100%
border: 0
border-radius: 3px
padding: 6px
@@ -147,11 +218,6 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
background: alpha(black, .3)
color: white
.-previous
.-center
.-next
margin:3px 0
.-previous
.-next
flex: 1
@@ -169,7 +235,7 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
.-pageInfo
display: inline-block
margin: 0 10px 3px
margin: 3px 10px
white-space: nowrap
.-pageJump
@@ -179,8 +245,20 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
text-align:center
.-pageSizeOptions
margin:0 10px 3px
margin: 3px 10px
.rt-noData
display:block
position:absolute
left:50%
top:50%
transform: translate(-50%, -50%)
background: alpha(white, .8)
transition: all .3s ease
z-index: 1
pointer-events: none
padding: 20px
color: alpha(black, .5)
.-loading
display:block
@@ -191,7 +269,7 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
bottom:0
background: alpha(white, .8)
transition: all .3s ease
z-index: 2
z-index: -1
opacity: 0
pointer-events: none
@@ -209,13 +287,13 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
&.-active
opacity: 1
z-index: 2
pointer-events: all
> div
transform: translateY(50%)
input
select
appearance: none
border: 1px solid rgba(0,0,0,0.1)
background: white
padding: 5px 7px
@@ -224,18 +302,9 @@ $easeOutBack = cubic-bezier(0.175, 0.885, 0.320, 1.275)
font-weight: normal
outline:none
.select-wrap
position:relative
display:inline-block
select
padding: 5px 15px 5px 7px
min-width:100px
&:after
content: ''
position: absolute
right: 8px
top: 50%
transform: translate(0, -50%)
border-color: #999 transparent transparent
border-style: solid
border-width: 5px 5px 2.5px
.rt-resizing
.rt-th
.rt-td
transition: none!important
cursor: col-resize
user-select none
+134
View File
@@ -0,0 +1,134 @@
export default Base =>
class extends Base {
componentWillMount () {
this.setStateWithData(this.getDataModel(this.getResolvedState()))
}
componentDidMount () {
this.fireFetchData()
}
componentWillReceiveProps (nextProps, nextState) {
const oldState = this.getResolvedState()
const newState = this.getResolvedState(nextProps, nextState)
// Do a deep compare of new and old `defaultOption` and
// if they are different reset `option = defaultOption`
const defaultableOptions = ['sorted', 'filtered', 'resized', 'expanded']
defaultableOptions.forEach(x => {
const defaultName = `default${x.charAt(0).toUpperCase() + x.slice(1)}`
if (
JSON.stringify(oldState[defaultName]) !==
JSON.stringify(newState[defaultName])
) {
newState[x] = newState[defaultName]
}
})
// If they change these table options, we need to reset defaults
// or else we could get into a state where the user has changed the UI
// and then disabled the ability to change it back.
// e.g. If `filterable` has changed, set `filtered = defaultFiltered`
const resettableOptions = ['sortable', 'filterable', 'resizable']
resettableOptions.forEach(x => {
if (oldState[x] !== newState[x]) {
const baseName = x.replace('able', '')
const optionName = `${baseName}ed`
const defaultName = `default${optionName.charAt(0).toUpperCase() +
optionName.slice(1)}`
newState[optionName] = newState[defaultName]
}
})
// Props that trigger a data update
if (
oldState.data !== newState.data ||
oldState.columns !== newState.columns ||
oldState.pivotBy !== newState.pivotBy ||
oldState.sorted !== newState.sorted ||
oldState.filtered !== newState.filtered
) {
this.setStateWithData(this.getDataModel(newState))
}
}
setStateWithData (newState, cb) {
const oldState = this.getResolvedState()
const newResolvedState = this.getResolvedState({}, newState)
const { freezeWhenExpanded } = newResolvedState
// Default to unfrozen state
newResolvedState.frozen = false
// If freezeWhenExpanded is set, check for frozen conditions
if (freezeWhenExpanded) {
// if any rows are expanded, freeze the existing data and sorting
const keys = Object.keys(newResolvedState.expanded)
for (var i = 0; i < keys.length; i++) {
if (newResolvedState.expanded[keys[i]]) {
newResolvedState.frozen = true
break
}
}
}
// If the data isn't frozen and either the data or
// sorting model has changed, update the data
if (
(oldState.frozen && !newResolvedState.frozen) ||
oldState.sorted !== newResolvedState.sorted ||
oldState.filtered !== newResolvedState.filtered ||
oldState.showFilters !== newResolvedState.showFilters ||
(!newResolvedState.frozen &&
oldState.resolvedData !== newResolvedState.resolvedData)
) {
// Handle collapseOnsortedChange & collapseOnDataChange
if (
(oldState.sorted !== newResolvedState.sorted &&
this.props.collapseOnSortingChange) ||
oldState.filtered !== newResolvedState.filtered ||
oldState.showFilters !== newResolvedState.showFilters ||
(oldState.sortedData &&
!newResolvedState.frozen &&
oldState.resolvedData !== newResolvedState.resolvedData &&
this.props.collapseOnDataChange)
) {
newResolvedState.expanded = {}
}
Object.assign(newResolvedState, this.getSortedData(newResolvedState))
}
// Set page to 0 if filters change
if (oldState.filtered !== newResolvedState.filtered) {
newResolvedState.page = 0
}
// Calculate pageSize all the time
if (newResolvedState.sortedData) {
newResolvedState.pages = newResolvedState.manual
? newResolvedState.pages
: Math.ceil(
newResolvedState.sortedData.length / newResolvedState.pageSize
)
newResolvedState.page = Math.max(
newResolvedState.page >= newResolvedState.pages
? newResolvedState.pages - 1
: newResolvedState.page,
0
)
}
return this.setState(newResolvedState, () => {
cb && cb()
if (
oldState.page !== newResolvedState.page ||
oldState.pageSize !== newResolvedState.pageSize ||
oldState.sorted !== newResolvedState.sorted ||
oldState.filtered !== newResolvedState.filtered
) {
this.fireFetchData()
}
})
}
}
+717
View File
@@ -0,0 +1,717 @@
import React from 'react'
import _ from './utils'
export default Base =>
class extends Base {
getResolvedState (props, state) {
const resolvedState = {
..._.compactObject(this.state),
..._.compactObject(this.props),
..._.compactObject(state),
..._.compactObject(props),
}
return resolvedState
}
getDataModel (newState) {
const {
columns,
pivotBy = [],
data,
pivotIDKey,
pivotValKey,
subRowsKey,
aggregatedKey,
nestingLevelKey,
originalKey,
indexKey,
groupedByPivotKey,
SubComponent,
} = newState
// Determine Header Groups
let hasHeaderGroups = false
columns.forEach(column => {
if (column.columns) {
hasHeaderGroups = true
}
})
let columnsWithExpander = [...columns]
let expanderColumn = columns.find(
col =>
col.expander ||
(col.columns && col.columns.some(col2 => col2.expander))
)
// The actual expander might be in the columns field of a group column
if (expanderColumn && !expanderColumn.expander) {
expanderColumn = expanderColumn.columns.find(col => col.expander)
}
// If we have SubComponent's we need to make sure we have an expander column
if (SubComponent && !expanderColumn) {
expanderColumn = { expander: true }
columnsWithExpander = [expanderColumn, ...columnsWithExpander]
}
const makeDecoratedColumn = (column, parentColumn) => {
let dcol
if (column.expander) {
dcol = {
...this.props.column,
...this.props.expanderDefaults,
...column,
}
} else {
dcol = {
...this.props.column,
...column,
}
}
// Ensure minWidth is not greater than maxWidth if set
if (dcol.maxWidth < dcol.minWidth) {
dcol.minWidth = dcol.maxWidth
}
if (parentColumn) {
dcol.parentColumn = parentColumn
}
// First check for string accessor
if (typeof dcol.accessor === 'string') {
dcol.id = dcol.id || dcol.accessor
const accessorString = dcol.accessor
dcol.accessor = row => _.get(row, accessorString)
return dcol
}
// Fall back to functional accessor (but require an ID)
if (dcol.accessor && !dcol.id) {
console.warn(dcol)
throw new Error(
'A column id is required if using a non-string accessor for column above.'
)
}
// Fall back to an undefined accessor
if (!dcol.accessor) {
dcol.accessor = d => undefined
}
return dcol
}
// Decorate the columns
const decorateAndAddToAll = (column, parentColumn) => {
const decoratedColumn = makeDecoratedColumn(column, parentColumn)
allDecoratedColumns.push(decoratedColumn)
return decoratedColumn
}
const allDecoratedColumns = []
const decoratedColumns = columnsWithExpander.map((column, i) => {
if (column.columns) {
return {
...column,
columns: column.columns.map(d => decorateAndAddToAll(d, column)),
}
} else {
return decorateAndAddToAll(column)
}
})
// Build the visible columns, headers and flat column list
let visibleColumns = decoratedColumns.slice()
let allVisibleColumns = []
visibleColumns = visibleColumns.map((column, i) => {
if (column.columns) {
const visibleSubColumns = column.columns.filter(
d =>
pivotBy.indexOf(d.id) > -1
? false
: _.getFirstDefined(d.show, true)
)
return {
...column,
columns: visibleSubColumns,
}
}
return column
})
visibleColumns = visibleColumns.filter(column => {
return column.columns
? column.columns.length
: pivotBy.indexOf(column.id) > -1
? false
: _.getFirstDefined(column.show, true)
})
// Find any custom pivot location
const pivotIndex = visibleColumns.findIndex(col => col.pivot)
// Handle Pivot Columns
if (pivotBy.length) {
// Retrieve the pivot columns in the correct pivot order
const pivotColumns = []
pivotBy.forEach(pivotID => {
const found = allDecoratedColumns.find(d => d.id === pivotID)
if (found) {
pivotColumns.push(found)
}
})
let PivotParentColumn = pivotColumns.reduce(
(prev, current) =>
prev && prev === current.parentColumn && current.parentColumn,
pivotColumns[0].parentColumn
)
let PivotGroupHeader = hasHeaderGroups && PivotParentColumn.Header
PivotGroupHeader = PivotGroupHeader || (() => <strong>Pivoted</strong>)
let pivotColumnGroup = {
Header: PivotGroupHeader,
columns: pivotColumns.map(col => ({
...this.props.pivotDefaults,
...col,
pivoted: true,
})),
}
// Place the pivotColumns back into the visibleColumns
if (pivotIndex >= 0) {
pivotColumnGroup = {
...visibleColumns[pivotIndex],
...pivotColumnGroup,
}
visibleColumns.splice(pivotIndex, 1, pivotColumnGroup)
} else {
visibleColumns.unshift(pivotColumnGroup)
}
}
// Build Header Groups
const headerGroups = []
let currentSpan = []
// A convenience function to add a header and reset the currentSpan
const addHeader = (columns, column) => {
headerGroups.push({
...this.props.column,
...column,
columns: columns,
})
currentSpan = []
}
// Build flast list of allVisibleColumns and HeaderGroups
visibleColumns.forEach((column, i) => {
if (column.columns) {
allVisibleColumns = allVisibleColumns.concat(column.columns)
if (currentSpan.length > 0) {
addHeader(currentSpan)
}
addHeader(column.columns, column)
return
}
allVisibleColumns.push(column)
currentSpan.push(column)
})
if (hasHeaderGroups && currentSpan.length > 0) {
addHeader(currentSpan)
}
// Access the data
const accessRow = (d, i, level = 0) => {
const row = {
[originalKey]: d,
[indexKey]: i,
[subRowsKey]: d[subRowsKey],
[nestingLevelKey]: level,
}
allDecoratedColumns.forEach(column => {
if (column.expander) return
row[column.id] = column.accessor(d)
})
if (row[subRowsKey]) {
row[subRowsKey] = row[subRowsKey].map((d, i) =>
accessRow(d, i, level + 1)
)
}
return row
}
let resolvedData = data.map((d, i) => accessRow(d, i))
// If pivoting, recursively group the data
const aggregate = rows => {
const aggregationValues = {}
aggregatingColumns.forEach(column => {
const values = rows.map(d => d[column.id])
aggregationValues[column.id] = column.aggregate(values, rows)
})
return aggregationValues
}
// TODO: Make it possible to fabricate nested rows without pivoting
const aggregatingColumns = allVisibleColumns.filter(
d => !d.expander && d.aggregate
)
if (pivotBy.length) {
const groupRecursively = (rows, keys, i = 0) => {
// This is the last level, just return the rows
if (i === keys.length) {
return rows
}
// Group the rows together for this level
let groupedRows = Object.entries(
_.groupBy(rows, keys[i])
).map(([key, value]) => {
return {
[pivotIDKey]: keys[i],
[pivotValKey]: key,
[keys[i]]: key,
[subRowsKey]: value,
[nestingLevelKey]: i,
[groupedByPivotKey]: true,
}
})
// Recurse into the subRows
groupedRows = groupedRows.map(rowGroup => {
let subRows = groupRecursively(rowGroup[subRowsKey], keys, i + 1)
return {
...rowGroup,
[subRowsKey]: subRows,
[aggregatedKey]: true,
...aggregate(subRows),
}
})
return groupedRows
}
resolvedData = groupRecursively(resolvedData, pivotBy)
}
return {
...newState,
resolvedData,
allVisibleColumns,
headerGroups,
allDecoratedColumns,
hasHeaderGroups,
}
}
getSortedData (resolvedState) {
const {
manual,
sorted,
filtered,
defaultFilterMethod,
resolvedData,
allVisibleColumns,
allDecoratedColumns,
} = resolvedState
const sortMethodsByColumnID = {}
allDecoratedColumns.filter(col => col.sortMethod).forEach(col => {
sortMethodsByColumnID[col.id] = col.sortMethod
})
// Resolve the data from either manual data or sorted data
return {
sortedData: manual
? resolvedData
: this.sortData(
this.filterData(
resolvedData,
filtered,
defaultFilterMethod,
allVisibleColumns
),
sorted,
sortMethodsByColumnID
),
}
}
fireFetchData () {
this.props.onFetchData(this.getResolvedState(), this)
}
getPropOrState (key) {
return _.getFirstDefined(this.props[key], this.state[key])
}
getStateOrProp (key) {
return _.getFirstDefined(this.state[key], this.props[key])
}
filterData (data, filtered, defaultFilterMethod, allVisibleColumns) {
let filteredData = data
if (filtered.length) {
filteredData = filtered.reduce((filteredSoFar, nextFilter) => {
const column = allVisibleColumns.find(x => x.id === nextFilter.id)
// Don't filter hidden columns or columns that have had their filters disabled
if (!column || column.filterable === false) {
return filteredSoFar
}
const filterMethod = column.filterMethod || defaultFilterMethod
// If 'filterAll' is set to true, pass the entire dataset to the filter method
if (column.filterAll) {
return filterMethod(nextFilter, filteredSoFar, column)
} else {
return filteredSoFar.filter(row => {
return filterMethod(nextFilter, row, column)
})
}
}, filteredData)
// Apply the filter to the subrows if we are pivoting, and then
// filter any rows without subcolumns because it would be strange to show
filteredData = filteredData
.map(row => {
if (!row[this.props.subRowsKey]) {
return row
}
return {
...row,
[this.props.subRowsKey]: this.filterData(
row[this.props.subRowsKey],
filtered,
defaultFilterMethod,
allVisibleColumns
),
}
})
.filter(row => {
if (!row[this.props.subRowsKey]) {
return true
}
return row[this.props.subRowsKey].length > 0
})
}
return filteredData
}
sortData (data, sorted, sortMethodsByColumnID = {}) {
if (!sorted.length) {
return data
}
const sortedData = (this.props.orderByMethod || _.orderBy)(
data,
sorted.map(sort => {
// Support custom sorting methods for each column
if (sortMethodsByColumnID[sort.id]) {
return (a, b) => {
return sortMethodsByColumnID[sort.id](a[sort.id], b[sort.id])
}
}
return (a, b) => {
return this.props.defaultSortMethod(a[sort.id], b[sort.id])
}
}),
sorted.map(d => !d.desc),
this.props.indexKey
)
sortedData.forEach(row => {
if (!row[this.props.subRowsKey]) {
return
}
row[this.props.subRowsKey] = this.sortData(
row[this.props.subRowsKey],
sorted,
sortMethodsByColumnID
)
})
return sortedData
}
getMinRows () {
return _.getFirstDefined(
this.props.minRows,
this.getStateOrProp('pageSize')
)
}
// User actions
onPageChange (page) {
const { onPageChange, collapseOnPageChange } = this.props
const newState = { page }
if (collapseOnPageChange) {
newState.expanded = {}
}
this.setStateWithData(newState, () => {
onPageChange && onPageChange(page)
})
}
onPageSizeChange (newPageSize) {
const { onPageSizeChange } = this.props
const { pageSize, page } = this.getResolvedState()
// Normalize the page to display
const currentRow = pageSize * page
const newPage = Math.floor(currentRow / newPageSize)
this.setStateWithData(
{
pageSize: newPageSize,
page: newPage,
},
() => {
onPageSizeChange && onPageSizeChange(newPageSize, newPage)
}
)
}
sortColumn (column, additive) {
const { sorted, skipNextSort, defaultSortDesc } = this.getResolvedState()
const firstSortDirection = column.hasOwnProperty('defaultSortDesc')
? column.defaultSortDesc
: defaultSortDesc
const secondSortDirection = !firstSortDirection
// we can't stop event propagation from the column resize move handlers
// attached to the document because of react's synthetic events
// so we have to prevent the sort function from actually sorting
// if we click on the column resize element within a header.
if (skipNextSort) {
this.setStateWithData({
skipNextSort: false,
})
return
}
const { onSortedChange } = this.props
let newSorted = _.clone(sorted || []).map(d => {
d.desc = _.isSortingDesc(d)
return d
})
if (!_.isArray(column)) {
// Single-Sort
const existingIndex = newSorted.findIndex(d => d.id === column.id)
if (existingIndex > -1) {
const existing = newSorted[existingIndex]
if (existing.desc === secondSortDirection) {
if (additive) {
newSorted.splice(existingIndex, 1)
} else {
existing.desc = firstSortDirection
newSorted = [existing]
}
} else {
existing.desc = secondSortDirection
if (!additive) {
newSorted = [existing]
}
}
} else {
if (additive) {
newSorted.push({
id: column.id,
desc: firstSortDirection,
})
} else {
newSorted = [
{
id: column.id,
desc: firstSortDirection,
},
]
}
}
} else {
// Multi-Sort
const existingIndex = newSorted.findIndex(d => d.id === column[0].id)
// Existing Sorted Column
if (existingIndex > -1) {
const existing = newSorted[existingIndex]
if (existing.desc === secondSortDirection) {
if (additive) {
newSorted.splice(existingIndex, column.length)
} else {
column.forEach((d, i) => {
newSorted[existingIndex + i].desc = firstSortDirection
})
}
} else {
column.forEach((d, i) => {
newSorted[existingIndex + i].desc = secondSortDirection
})
}
if (!additive) {
newSorted = newSorted.slice(existingIndex, column.length)
}
} else {
// New Sort Column
if (additive) {
newSorted = newSorted.concat(
column.map(d => ({
id: d.id,
desc: firstSortDirection,
}))
)
} else {
newSorted = column.map(d => ({
id: d.id,
desc: firstSortDirection,
}))
}
}
}
this.setStateWithData(
{
page:
(!sorted.length && newSorted.length) || !additive
? 0
: this.state.page,
sorted: newSorted,
},
() => {
onSortedChange && onSortedChange(newSorted, column, additive)
}
)
}
filterColumn (column, value) {
const { filtered } = this.getResolvedState()
const { onFilteredChange } = this.props
// Remove old filter first if it exists
const newFiltering = (filtered || []).filter(x => {
if (x.id !== column.id) {
return true
}
})
if (value !== '') {
newFiltering.push({
id: column.id,
value: value,
})
}
this.setStateWithData(
{
filtered: newFiltering,
},
() => {
onFilteredChange && onFilteredChange(newFiltering, column, value)
}
)
}
resizeColumnStart (event, column, isTouch) {
event.stopPropagation()
const parentWidth = event.target.parentElement.getBoundingClientRect()
.width
let pageX
if (isTouch) {
pageX = event.changedTouches[0].pageX
} else {
pageX = event.pageX
}
this.trapEvents = true
this.setStateWithData(
{
currentlyResizing: {
id: column.id,
startX: pageX,
parentWidth: parentWidth,
},
},
() => {
if (isTouch) {
document.addEventListener('touchmove', this.resizeColumnMoving)
document.addEventListener('touchcancel', this.resizeColumnEnd)
document.addEventListener('touchend', this.resizeColumnEnd)
} else {
document.addEventListener('mousemove', this.resizeColumnMoving)
document.addEventListener('mouseup', this.resizeColumnEnd)
document.addEventListener('mouseleave', this.resizeColumnEnd)
}
}
)
}
resizeColumnMoving (event) {
event.stopPropagation()
const { onResizedChange } = this.props
const { resized, currentlyResizing } = this.getResolvedState()
// Delete old value
const newResized = resized.filter(x => x.id !== currentlyResizing.id)
let pageX
if (event.type === 'touchmove') {
pageX = event.changedTouches[0].pageX
} else if (event.type === 'mousemove') {
pageX = event.pageX
}
// Set the min size to 10 to account for margin and border or else the group headers don't line up correctly
const newWidth = Math.max(
currentlyResizing.parentWidth + pageX - currentlyResizing.startX,
11
)
newResized.push({
id: currentlyResizing.id,
value: newWidth,
})
this.setStateWithData(
{
resized: newResized,
},
() => {
onResizedChange && onResizedChange(newResized, event)
}
)
}
resizeColumnEnd (event) {
event.stopPropagation()
let isTouch = event.type === 'touchend' || event.type === 'touchcancel'
if (isTouch) {
document.removeEventListener('touchmove', this.resizeColumnMoving)
document.removeEventListener('touchcancel', this.resizeColumnEnd)
document.removeEventListener('touchend', this.resizeColumnEnd)
}
// If its a touch event clear the mouse one's as well because sometimes
// the mouseDown event gets called as well, but the mouseUp event doesn't
document.removeEventListener('mousemove', this.resizeColumnMoving)
document.removeEventListener('mouseup', this.resizeColumnEnd)
document.removeEventListener('mouseleave', this.resizeColumnEnd)
// The touch events don't propagate up to the sorting's onMouseDown event so
// no need to prevent it from happening or else the first click after a touch
// event resize will not sort the column.
if (!isTouch) {
this.setStateWithData({
skipNextSort: true,
currentlyResizing: false,
})
}
}
}
+69 -47
View File
@@ -1,60 +1,79 @@
import React from 'react'
import React, { Component } from 'react'
import classnames from 'classnames'
//
// import _ from './utils'
const defaultButton = (props) => (
<button {...props} className='-btn'>{props.children}</button>
)
const defaultButton = props =>
<button type='button' {...props} className='-btn'>
{props.children}
</button>
export default React.createClass({
getInitialState () {
return {
page: this.props.currentPage
export default class ReactTablePagination extends Component {
constructor (props) {
super()
this.getSafePage = this.getSafePage.bind(this)
this.changePage = this.changePage.bind(this)
this.applyPage = this.applyPage.bind(this)
this.state = {
page: props.page,
}
},
}
componentWillReceiveProps (nextProps) {
this.setState({page: nextProps.currentPage})
},
this.setState({ page: nextProps.page })
}
getSafePage (page) {
return Math.min(Math.max(page, 0), this.props.pagesLength - 1)
},
if (isNaN(page)) {
page = this.props.page
}
return Math.min(Math.max(page, 0), this.props.pages - 1)
}
changePage (page) {
page = this.getSafePage(page)
this.setState({page})
this.props.onChange(page)
},
this.setState({ page })
if (this.props.page !== page) {
this.props.onPageChange(page)
}
}
applyPage (e) {
e && e.preventDefault()
const page = this.state.page
this.changePage(page === '' ? this.props.currentPage : page)
},
this.changePage(page === '' ? this.props.page : page)
}
render () {
const {
currentPage,
pagesLength,
// Computed
pages,
// Props
page,
showPageSizeOptions,
pageSizeOptions,
pageSize,
showPageJump,
canPrevious,
canNext,
onPageSizeChange
onPageSizeChange,
className,
PreviousComponent = defaultButton,
NextComponent = defaultButton,
} = this.props
const PreviousComponent = this.props.previousComponent || defaultButton
const NextComponent = this.props.nextComponent || defaultButton
return (
<div
className={classnames(this.props.paginationClassName, '-pagination')}
className={classnames(className, '-pagination')}
style={this.props.paginationStyle}
>
<div className='-previous'>
<PreviousComponent
onClick={(e) => {
onClick={e => {
if (!canPrevious) return
this.changePage(currentPage - 1)
this.changePage(page - 1)
}}
disabled={!canPrevious}
>
@@ -63,52 +82,55 @@ export default React.createClass({
</div>
<div className='-center'>
<span className='-pageInfo'>
{this.props.pageText} {showPageJump ? (
<form className='-pageJump'
onSubmit={this.applyPage}
>
{this.props.pageText}{' '}
{showPageJump
? <div className='-pageJump'>
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value
const page = val - 1
if (val === '') {
return this.setState({page: val})
return this.setState({ page: val })
}
this.setState({page: this.getSafePage(page)})
this.setState({ page: this.getSafePage(page) })
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
onKeyPress={e => {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage()
}
}}
/>
</form>
) : (
<span className='-currentPage'>{currentPage + 1}</span>
)} {this.props.ofText} <span className='-totalPages'>{pagesLength}</span>
</div>
: <span className='-currentPage'>
{page + 1}
</span>}{' '}
{this.props.ofText}{' '}
<span className='-totalPages'>{pages || 1}</span>
</span>
{showPageSizeOptions && (
{showPageSizeOptions &&
<span className='select-wrap -pageSizeOptions'>
<select
onChange={(e) => onPageSizeChange(Number(e.target.value))}
onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize}
>
{pageSizeOptions.map((option, i) => {
return (
<option
key={i}
value={option}>
<option key={i} value={option}>
{option} {this.props.rowsText}
</option>
)
})}
</select>
</span>
)}
</span>}
</div>
<div className='-next'>
<NextComponent
onClick={(e) => {
onClick={e => {
if (!canNext) return
this.changePage(currentPage + 1)
this.changePage(page + 1)
}}
disabled={!canNext}
>
@@ -118,4 +140,4 @@ export default React.createClass({
</div>
)
}
})
}
+163 -48
View File
@@ -1,37 +1,51 @@
import React from 'react'
import classnames from 'classnames'
//
export default {
get,
set,
takeRight,
last,
orderBy,
range,
clone,
remove,
getFirstDefined
clone,
getFirstDefined,
sum,
makeTemplateComponent,
groupBy,
isArray,
splitProps,
compactObject,
isSortingDesc,
normalizeComponent,
asPx,
}
function remove (a, b) {
return a.filter(function (o, i) {
var r = b(o)
if (r) {
a.splice(i, 1)
return true
}
return false
})
}
function get (a, b) {
if (isArray(b)) {
b = b.join('.')
function get (obj, path, def) {
if (!path) {
return obj
}
return b
.replace('[', '.').replace(']', '')
.split('.')
.reduce(
function (obj, property) {
return obj[property]
}, a
)
const pathObj = makePathArray(path)
let val
try {
val = pathObj.reduce((current, pathPart) => current[pathPart], obj)
} catch (e) {}
return typeof val !== 'undefined' ? val : def
}
function set (obj = {}, path, value) {
const keys = makePathArray(path)
let keyPart
let cursor = obj
while ((keyPart = keys.shift()) && keys.length) {
if (!cursor[keyPart]) {
cursor[keyPart] = {}
}
cursor = cursor[keyPart]
}
cursor[keyPart] = value
return obj
}
function takeRight (arr, n) {
@@ -51,39 +65,47 @@ function range (n) {
return arr
}
function orderBy (arr, funcs, dirs) {
return arr.sort((a, b) => {
function orderBy (arr, funcs, dirs, indexKey) {
return arr.sort((rowA, rowB) => {
for (let i = 0; i < funcs.length; i++) {
const comp = funcs[i]
const ca = comp(a)
const cb = comp(b)
const desc = dirs[i] === false || dirs[i] === 'desc'
if (ca > cb) {
return desc ? -1 : 1
}
if (ca < cb) {
return desc ? 1 : -1
const sortInt = comp(rowA, rowB)
if (sortInt) {
return desc ? -sortInt : sortInt
}
}
return 0
// Use the row index for tie breakers
return dirs[0]
? rowA[indexKey] - rowB[indexKey]
: rowB[indexKey] - rowA[indexKey]
})
}
function remove (a, b) {
return a.filter(function (o, i) {
var r = b(o)
if (r) {
a.splice(i, 1)
return true
}
return false
})
}
function clone (a) {
return JSON.parse(JSON.stringify(a, function (key, value) {
if (typeof value === 'function') {
return value.toString()
}
return value
}))
}
// ########################################################################
// Helpers
// ########################################################################
function isArray (a) {
return Array.isArray(a)
try {
return JSON.parse(
JSON.stringify(a, (key, value) => {
if (typeof value === 'function') {
return value.toString()
}
return value
})
)
} catch (e) {
return a
}
}
function getFirstDefined (...args) {
@@ -93,3 +115,96 @@ function getFirstDefined (...args) {
}
}
}
function sum (arr) {
return arr.reduce((a, b) => {
return a + b
}, 0)
}
function makeTemplateComponent (compClass, displayName) {
if (!displayName) {
throw new Error('No displayName found for template component:', compClass)
}
const cmp = ({ children, className, ...rest }) =>
<div className={classnames(compClass, className)} {...rest}>
{children}
</div>
cmp.displayName = displayName
return cmp
}
function groupBy (xs, key) {
return xs.reduce((rv, x, i) => {
const resKey = typeof key === 'function' ? key(x, i) : x[key]
rv[resKey] = isArray(rv[resKey]) ? rv[resKey] : []
rv[resKey].push(x)
return rv
}, {})
}
function asPx (value) {
value = Number(value)
return Number.isNaN(value) ? null : value + 'px'
}
function isArray (a) {
return Array.isArray(a)
}
// ########################################################################
// Non-exported Helpers
// ########################################################################
function makePathArray (obj) {
return flattenDeep(obj)
.join('.')
.replace(/\[/g, '.')
.replace(/\]/g, '')
.split('.')
}
function flattenDeep (arr, newArr = []) {
if (!isArray(arr)) {
newArr.push(arr)
} else {
for (var i = 0; i < arr.length; i++) {
flattenDeep(arr[i], newArr)
}
}
return newArr
}
function splitProps ({ className, style, ...rest }) {
return {
className,
style,
rest: rest || {},
}
}
function compactObject (obj) {
const newObj = {}
for (var key in obj) {
if (
obj.hasOwnProperty(key) &&
obj[key] !== undefined &&
typeof obj[key] !== 'undefined'
) {
newObj[key] = obj[key]
}
}
return newObj
}
function isSortingDesc (d) {
return !!(d.sort === 'desc' || d.desc === true || d.asc === false)
}
function normalizeComponent (Comp, params = {}, fallback = Comp) {
return typeof Comp === 'function'
? Object.getPrototypeOf(Comp).isReactComponent
? <Comp {...params} />
: Comp(params)
: fallback
}
+20
View File
@@ -0,0 +1,20 @@
const webpack = require('webpack')
module.exports = {
entry: './lib/index.js',
output: {
filename: './react-table.js',
libraryTarget: 'umd',
library: 'ReactTable'
},
externals: {
react: {
root: 'React',
commonjs2: 'react',
commonjs: 'react',
amd: 'react'
}
},
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
}
+1416 -890
View File
File diff suppressed because it is too large Load Diff