├── .babelrc
├── .eslintrc
├── .gitignore
├── .npmignore
├── LICENSE
├── README.md
├── changelog.md
├── example
├── components
│ ├── accordion.js
│ ├── filepicker.js
│ └── pager.js
├── index.html
├── index.js
├── root.js
└── style.scss
├── index.d.ts
├── lib
├── _config.scss
├── accordion
│ ├── _config.scss
│ ├── accordion.js
│ ├── chord.js
│ ├── index.d.ts
│ ├── index.js
│ └── theme.scss
├── filepicker
│ ├── _config.scss
│ ├── filepicker.js
│ ├── index.d.ts
│ ├── index.js
│ └── theme.scss
├── identifiers.js
├── index.js
└── pager
│ ├── _config.scss
│ ├── index.d.ts
│ ├── index.js
│ ├── page.js
│ ├── pager.js
│ └── theme.scss
├── package.json
├── screenshots
└── rta.gif
├── server.js
├── src
├── _config.scss
├── accordion
│ ├── _config.scss
│ ├── accordion.js
│ ├── chord.js
│ ├── index.d.ts
│ ├── index.js
│ ├── readme.md
│ └── theme.scss
├── filepicker
│ ├── _config.scss
│ ├── filepicker.js
│ ├── index.d.ts
│ ├── index.js
│ ├── readme.md
│ └── theme.scss
├── identifiers.js
├── index.js
└── pager
│ ├── _config.scss
│ ├── index.d.ts
│ ├── index.js
│ ├── page.js
│ ├── pager.js
│ ├── readme.md
│ └── theme.scss
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-0", "react"]
3 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "node": true,
5 | "mocha": true,
6 | "es6": true
7 | },
8 |
9 | "ecmaFeatures": {
10 | "jsx": true,
11 | "templateStrings": true,
12 | "superInFunctions": false,
13 | "classes": true,
14 | "modules": true
15 | },
16 |
17 | "parser": "babel-eslint",
18 |
19 | "plugins": [
20 | "babel",
21 | "react"
22 | ],
23 |
24 | "rules": {
25 | "block-scoped-var": [0],
26 | "brace-style": [2, "1tbs", {
27 | "allowSingleLine": true
28 | }],
29 | "camelcase": [0],
30 | "comma-dangle": [2, "never"],
31 | "comma-spacing": [2],
32 | "comma-style": [2, "last"],
33 | "complexity": [0, 11],
34 | "constructor-super": [2],
35 | "consistent-return": [0],
36 | "consistent-this": [0, "that"],
37 | "curly": [2, "multi-line"],
38 | "default-case": [2],
39 | "dot-notation": [2, {
40 | "allowKeywords": true
41 | }],
42 | "eol-last": [2],
43 | "eqeqeq": [2],
44 | "func-names": [0],
45 | "func-style": [0, "declaration"],
46 | "generator-star-spacing": [2, "after"],
47 | "guard-for-in": [0],
48 | "handle-callback-err": [0],
49 | "key-spacing": [2, {
50 | "beforeColon": false,
51 | "afterColon": true
52 | }],
53 | "quotes": [2, "single", "avoid-escape"],
54 | "max-depth": [0, 4],
55 | "max-len": [0, 80, 4],
56 | "max-nested-callbacks": [0, 2],
57 | "max-params": [0, 3],
58 | "max-statements": [0, 10],
59 | "new-parens": [2],
60 | "new-cap": [0],
61 | "newline-after-var": [0],
62 | "no-alert": [2],
63 | "no-array-constructor": [2],
64 | "no-bitwise": [0],
65 | "no-caller": [2],
66 | "no-catch-shadow": [2],
67 | "no-cond-assign": [2],
68 | "no-console": [0],
69 | "no-constant-condition": [1],
70 | "no-continue": [2],
71 | "no-control-regex": [2],
72 | "no-debugger": [2],
73 | "no-delete-var": [2],
74 | "no-div-regex": [0],
75 | "no-dupe-args": [2],
76 | "no-dupe-keys": [2],
77 | "no-duplicate-case": [2],
78 | "no-else-return": [0],
79 | "no-empty": [2],
80 | "no-empty-character-class": [2],
81 | "no-eq-null": [0],
82 | "no-eval": [2],
83 | "no-ex-assign": [2],
84 | "no-extend-native": [1],
85 | "no-extra-bind": [2],
86 | "no-extra-boolean-cast": [2],
87 | "no-extra-parens": [0],
88 | "no-extra-semi": [1],
89 | "no-fallthrough": [2],
90 | "no-floating-decimal": [2],
91 | "no-func-assign": [2],
92 | "no-implied-eval": [2],
93 | "no-inline-comments": [0],
94 | "no-inner-declarations": [2, "functions"],
95 | "no-invalid-regexp": [2],
96 | "no-irregular-whitespace": [2],
97 | "no-iterator": [2],
98 | "no-label-var": [2],
99 | "no-labels": [2],
100 | "no-lone-blocks": [2],
101 | "no-lonely-if": [2],
102 | "no-loop-func": [2],
103 | "no-mixed-requires": [0, false],
104 | "no-mixed-spaces-and-tabs": [2, false],
105 | "no-multi-spaces": [2],
106 | "no-multi-str": [2],
107 | "no-multiple-empty-lines": [2, {
108 | "max": 2
109 | }],
110 | "no-native-reassign": [1],
111 | "no-negated-in-lhs": [2],
112 | "no-nested-ternary": [0],
113 | "no-new": [2],
114 | "no-new-func": [2],
115 | "no-new-object": [2],
116 | "no-new-require": [0],
117 | "no-new-wrappers": [2],
118 | "no-obj-calls": [2],
119 | "no-octal": [2],
120 | "no-octal-escape": [2],
121 | "no-path-concat": [0],
122 | "no-param-reassign": [2],
123 | "no-plusplus": [0],
124 | "no-process-env": [0],
125 | "no-process-exit": [2],
126 | "no-proto": [2],
127 | "no-redeclare": [2],
128 | "no-regex-spaces": [2],
129 | "no-reserved-keys": [0],
130 | "no-restricted-modules": [0],
131 | "no-return-assign": [2],
132 | "no-script-url": [2],
133 | "no-self-compare": [0],
134 | "no-sequences": [2],
135 | "no-shadow": [2],
136 | "no-shadow-restricted-names": [2],
137 | "semi-spacing": [2],
138 | "no-spaced-func": [2],
139 | "no-sparse-arrays": [2],
140 | "no-sync": [0],
141 | "no-ternary": [0],
142 | "no-this-before-super": [2],
143 | "no-throw-literal": [2],
144 | "no-trailing-spaces": [2],
145 | "no-undef": [2],
146 | "no-undef-init": [2],
147 | "no-undefined": [0],
148 | "no-underscore-dangle": [0],
149 | "no-unreachable": [2],
150 | "no-unused-expressions": [2, {
151 | "allowShortCircuit": true
152 | }],
153 | "no-unused-vars": [1, {
154 | "vars": "all",
155 | "args": "after-used"
156 | }],
157 | "no-use-before-define": [2, "nofunc"],
158 | "no-var": [2],
159 | "no-void": [0],
160 | "no-warning-comments": [0, {
161 | "terms": ["todo", "fixme", "xxx"],
162 | "location": "start"
163 | }],
164 | "no-with": [2],
165 | "one-var": [0],
166 | "operator-assignment": [0, "always"],
167 | "operator-linebreak": [2, "before"],
168 | "padded-blocks": [0],
169 | "prefer-const": [2],
170 | "prefer-spread": [2],
171 | "quote-props": [0],
172 | "radix": [0],
173 | "semi": [2],
174 | "sort-vars": [0],
175 | "keyword-spacing": [2, {"after": true}],
176 | "space-before-function-paren": [2, { "anonymous": "always", "named": "always" }],
177 | "space-before-blocks": [0, "always"],
178 | "space-in-brackets": [0, "never", {
179 | "singleValue": true,
180 | "arraysInArrays": false,
181 | "arraysInObjects": false,
182 | "objectsInArrays": true,
183 | "objectsInObjects": true,
184 | "propertyName": false
185 | }],
186 | "space-in-parens": [2, "never"],
187 | "space-infix-ops": [2],
188 | "space-unary-ops": [2, {
189 | "words": true,
190 | "nonwords": false
191 | }],
192 | "spaced-line-comment": [0, "always"],
193 | "strict": [1],
194 | "use-isnan": [2],
195 | "valid-jsdoc": [0],
196 | "valid-typeof": [2],
197 | "vars-on-top": [0],
198 | "wrap-iife": [2],
199 | "wrap-regex": [2],
200 | "yoda": [2, "never", {
201 | "exceptRange": true
202 | }],
203 | "babel/object-shorthand": [2],
204 | "react/display-name": 0,
205 | "react/jsx-boolean-value": 1,
206 | "react/jsx-closing-bracket-location": 0,
207 | "react/jsx-curly-spacing": 1,
208 | "react/jsx-max-props-per-line": 0,
209 | "react/jsx-indent-props": 0,
210 | "react/jsx-no-duplicate-props": 1,
211 | "react/jsx-no-undef": 1,
212 | "react/jsx-pascal-case": 1,
213 | "react/sort-prop-types": 1,
214 | "react/jsx-sort-props": 0,
215 | "react/jsx-uses-react": 1,
216 | "react/jsx-uses-vars": 1,
217 | "react/no-danger": 0,
218 | "react/no-did-mount-set-state": 0,
219 | "react/no-did-update-set-state": 1,
220 | "react/no-multi-comp": 0,
221 | "react/no-unknown-property": 1,
222 | "react/prop-types": [2, {"ignore": ["onMouseDown", "onTouchStart"]}],
223 | "react/react-in-jsx-scope": 1,
224 | "react/self-closing-comp": 1,
225 | "react/sort-comp": 1
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 | node_modules
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .*rc
2 | .gitignore
3 | server.js
4 | webpack.config.*
5 | example
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 react-toolbox-additions author
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Additional components for react-toolbox components library
2 |
3 | [](https://www.npmjs.org/package/react-toolbox-additions)
4 |
5 | The project provides additions for react-toolbox library (http://react-toolbox.com/),
6 | which are not defined at material design and therefore were not included to original react-toolbox components library,
7 | but it could be useful to have.
8 |
9 | ## Installation
10 |
11 | React Toolbox can be installed as an [npm package](https://www.npmjs.org/package/react-toolbox-additions):
12 |
13 | ```bash
14 | $ npm install react-toolbox-additions
15 | ```
16 | ## Prerequisites
17 |
18 | React Toolbox Additions require uses [react-toolbox](https://www.npmjs.com/package/react-toolbox) components library and [react](https://www.npmjs.com/package/react).
19 |
20 | Like react-toolbox authors I also would recommend [webpack](https://webpack.github.io/) to use module bundler.
21 |
22 | The components can be customized via themes by using [react-css-themr](https://github.com/javivelasco/react-css-themr) which is also used by React Toolbox to make component easily themeable.
23 |
24 | ## Basic usage
25 |
26 | Examples how to use.
27 |
28 | Pager:
29 |
30 | ```js
31 | import Pager from 'react-toolbox-additions/lib/pager';
32 | import FontIcon from 'react-toolbox-additions/lib/font_icon';
33 |
34 | const PagerTest = () => {
35 |
36 | onPageChange = (newPage, oldPage) => {
37 | console.info('Selected page : ' + newPage + ', Previous page: ' + oldPage);
38 | }
39 |
40 | return (
41 | )}
43 | nextButtonLabel={( )}
44 | rangeLeftButtonLabel={( )}
45 | rangeRightButtonLabel={( )}
46 | totalPages={29}
47 | currentPage={5}
48 | visiblePagesBlockSize={3}
49 | onPageChange={onPageChange}
50 | />
51 | );
52 | };
53 | ```
54 |
55 | Accordion:
56 |
57 | ```jsx
58 | import React, { PropTypes } from 'react';
59 | import FontIcon from 'react-toolbox/lib/font_icon';
60 | import Input from 'react-toolbox/lib/input';
61 | import {Button} from 'react-toolbox/lib/button';
62 | import { ListCheckbox, ListSubHeader, List, ListItem, ListDivider, ListItemText, ListItemContent } from 'react-toolbox/lib/list';
63 |
64 | import { Accordion, Chord } from 'react-toolbox-additions/lib/accordion';
65 | import style from '../style';
66 |
67 | class AccordionTest extends React.Component {
68 |
69 | static propTypes = {
70 | };
71 |
72 | static defaultProps = {
73 | }
74 |
75 | state = {
76 | index: 0
77 | }
78 |
79 | onChange = (idx) => {
80 | this.setState({
81 | index: idx
82 | });
83 | }
84 |
85 | onActive1 = () => {
86 | console.info('Selected chord: ' + this.state.index);
87 | }
88 |
89 | onActive2 = () => {
90 | console.info('Selected chord: ' + this.state.index);
91 | }
92 |
93 | onActive3 = () => {
94 | console.info('Selected chord: ' + this.state.index);
95 | }
96 |
97 | render () {
98 |
99 | return (
100 |
105 |
109 |
110 | The project provides additions for react-toolbox which are not defined at material design and therefore were not included to original react-toolbox components library but it could be useful to have.
111 |
112 |
113 | }
115 | label='Number Two'
116 | onActive={this.onActive2}
117 | >
118 |
119 |
124 |
125 |
128 |
129 |
130 |
131 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | );
147 | }
148 | }
149 | ```
150 |
151 | Also important notice from authors of react-toolbox:
152 | "Take into account that any required style will be included in the final CSS so your final would include `Button` styles in this case. It's more convenient to import components this way (or with raw imports) because if you require from the project root, every stylesheet of React Toolbox will be included, even if you don't use it."
153 |
154 | ## Importing components
155 |
156 | The project inherits the same style of component structures that is in react-toolbox project, what makes it easy to use for everybody who is familiar with react-toolbox components structure.
157 | ```
158 | |- /pager
159 | |---- pager.js
160 | |---- _config.scss
161 | |---- index.js
162 | |---- readme.md
163 | |---- theme.scss
164 | ```
165 |
166 | ### Bundled component
167 |
168 | ```js
169 | import { Pager } from 'react-toolbox-additions/lib/pager';
170 | import { Accordion, Chord } from 'react-toolbox-additions/lib/accordion';
171 | import { FilePicker } from 'react-toolbox-additions/lib/filepicker';
172 | ```
173 |
174 | ## Screenshots
175 |
176 |
177 |
178 |
179 |
180 | ## Authors and Contributors
181 |
182 | The project is being initially developed and maintained by [Max Komlev](https://github.com/MaximKomlev).
183 |
184 | Steps to build project and run example locally.
185 |
186 | ```
187 | $ git clone https://github.com/MaximKomlev/react-toolbox-additions.git
188 | $ npm install
189 | $ npm run build
190 | $ npm start
191 | ```
192 |
193 | Local example will be available at `http://localhost:8000/`.
194 |
195 | ## Components in bundle
196 |
197 | Currently the library implements Pager, FilePicker and Accordion components.
198 |
199 | ## Changes
200 |
201 | [The log of changes](https://github.com/MaximKomlev/react-toolbox-additions/blob/master/changelog.md).
202 |
203 | ## License
204 |
205 | This project is licensed under the terms of the [MIT license](https://github.com/MaximKomlev/react-toolbox-additions/blob/master/LICENSE).
206 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # Change Log
2 | All notable changes to this project will be documented in this file.
3 |
4 | ## [Release 1.3.9] - 01/05/2016
5 | ### Updated
6 | - Fixed typing at readme.
7 |
8 | ## [Release 1.3.8] - 01/04/2016
9 | ### Updated
10 | - Fixed misversioning.
11 |
12 | ## [Release 1.3.7] - 02/04/2016
13 | ### Updated
14 | - To follow base project (react-toolbox).
15 |
16 | ## [Release 1.3.6] - 12/14/2016
17 | ### Updated
18 | - Exported components.
19 |
20 | ## [Release 1.3.5] - 12/14/2016
21 | ### Updated
22 | - Dependencies.
23 |
24 | ## [Release 1.3.4] - 12/14/2016
25 | ### Added
26 | - Chord icon and postIcon customization.
27 |
28 | ## [Release 1.3.3] - 12/06/2016
29 | ### Fixed
30 | - Chord resizing and content growing.
31 |
32 | ## [Release 1.3.2] - 12/05/2016
33 | ### Fixed
34 | - Chord icon styling.
35 |
36 | ## [Release 1.3.1] - 12/05/2016
37 | ### Fixed
38 | - Component resizing.
39 |
40 | ### Updated
41 | - Sample.
42 |
43 | ### Changed
44 | - labelIcon and labelPostIcon properties to take value as component or string.
45 |
46 | ## [Release 1.3.0] - 12/05/2016
47 | ### Added
48 | - Initial version of Accordion component.
49 |
50 | ## [Release 1.2.4] - 11/29/2016
51 | ### Added
52 | - Change log at readme.
53 |
54 | ## [Release 1.2.3] - 11/29/2016
55 | ### Added
56 | - Styling for first and last pages buttons.
57 |
58 | ### Fixed
59 | - Adjasment of buttons number according to visibleBlockSize.
60 |
61 | ## [Release 1.2.2] - 11/28/2016
62 | ### Added
63 | - Missed file.
64 |
65 | ## [Release 1.2.1] - 11/28/2016
66 | ### Added
67 | - More examples of pager to use.
68 |
69 | ### Fixed
70 | - Fixed runtime react warning on filepicker component.
71 | - Fixed ripple appearing on page button click.
72 |
73 | ### Changed
74 | - Updated default layout of Pager component from flex to inline-block.
75 | - Updated default layout of FilePicker component from flex to inline-block.
76 |
77 | ## [Release 1.1.2] - 11/16/2016
78 | ### Changed
79 | - Changed FilePicker Public Interface to provide more flexible way to customize/change behaviour or view of component.
80 | - Updated Sample of use.
81 |
82 | ## [Release 1.0.1] - 10/30/2016
83 | ### Added
84 | - Initial Version.
85 |
--------------------------------------------------------------------------------
/example/components/accordion.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import FontIcon from 'react-toolbox/lib/font_icon';
3 | import Input from 'react-toolbox/lib/input';
4 | import {Button} from 'react-toolbox/lib/button';
5 | import { ListCheckbox, ListSubHeader, List, ListItem, ListDivider, ListItemText, ListItemContent } from 'react-toolbox/lib/list';
6 |
7 | import {Accordion, Chord} from '../../lib/accordion';
8 | import style from '../style';
9 |
10 | class AccordionTest extends React.Component {
11 |
12 | static propTypes = {
13 | };
14 |
15 | static defaultProps = {
16 | }
17 |
18 | state = {
19 | index1: 0,
20 | index2: 0
21 | }
22 |
23 | onChange1 = (idx) => {
24 | this.setState({
25 | index1: idx
26 | });
27 | }
28 |
29 | onChange2 = (idx) => {
30 | this.setState({
31 | index2: idx
32 | });
33 | }
34 |
35 | onActive1 = () => {
36 | console.info('Selected chord: ' + this.state.index1);
37 | }
38 |
39 | onActive2 = () => {
40 | console.info('Selected chord: ' + this.state.index1);
41 | }
42 |
43 | onActive3 = () => {
44 | console.info('Selected chord: ' + this.state.index1);
45 | }
46 |
47 | render () {
48 |
49 | return (
50 |
51 | Accordion
52 | Accordion component.
53 |
54 |
55 |
60 |
64 |
65 | The project provides additions for react-toolbox which are not defined at material design and therefore were not included to original react-toolbox components library but it could be useful to have.
66 |
67 |
68 | }
70 | label='Number Two'
71 | onActive={this.onActive2}
72 | >
73 |
74 |
79 |
80 |
83 |
84 |
85 |
86 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | Themed accordion component.
105 |
106 |
107 |
113 |
116 |
117 | The project provides additions for react-toolbox which are not defined at material design and therefore were not included to original react-toolbox components library but it could be useful to have.
118 |
119 |
120 | }
122 | label='Number Two'
123 | >
124 |
125 |
130 |
131 |
134 |
135 |
136 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 | );
153 | }
154 | }
155 |
156 | export default AccordionTest;
157 |
--------------------------------------------------------------------------------
/example/components/filepicker.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 |
3 | import FilePicker from '../../lib/filepicker';
4 | import style from '../style';
5 |
6 | class FilePickerTest extends React.Component {
7 |
8 | state = {
9 | }
10 |
11 | onChange1 (fobj, fname) {
12 | console.info('Selected file1 : ' + fname);
13 | }
14 |
15 | onChange2 (fobj, fname) {
16 | console.info('Selected file2 : ' + fname);
17 | }
18 |
19 | onChange3 (fobj, fname) {
20 | console.info('Selected file3 : ' + fname);
21 | }
22 |
23 | onChange4 (fobj, fname) {
24 | console.info('Selected file4 : ' + fname);
25 | }
26 |
27 | render () {
28 |
29 | return (
30 |
31 | FilePicker
32 | FilePicker based on ToolBox components.
33 |
34 |
35 |
36 |
41 |
42 |
47 |
48 |
54 |
55 |
59 |
60 |
61 |
62 |
63 | );
64 | }
65 | }
66 |
67 | export default FilePickerTest;
68 |
--------------------------------------------------------------------------------
/example/components/pager.js:
--------------------------------------------------------------------------------
1 | import React, { PropTypes } from 'react';
2 | import FontIcon from 'react-toolbox/lib/font_icon';
3 | import Input from 'react-toolbox/lib/input';
4 |
5 | import Pager from '../../lib/pager';
6 | import style from '../style';
7 |
8 | class PagerTest extends React.Component {
9 |
10 | static propTypes = {
11 | visiblePagesBlockSize: PropTypes.number
12 | };
13 |
14 | static defaultProps = {
15 | visiblePagesBlockSize: 3
16 | }
17 |
18 | state = {
19 | totalPages: 29,
20 | currentPage: 5
21 | }
22 |
23 | onInputChange = (name, value) => {
24 | const state = this.state;
25 |
26 | state[name] = value;
27 |
28 | this.setState({
29 | ...state
30 | });
31 | }
32 |
33 | onPageChange1 = (newPage, oldPage) => {
34 | console.info('Selected page : ' + newPage + ', Previous page: ' + oldPage);
35 | }
36 |
37 | onPageChange2 = (newPage, oldPage) => {
38 | console.info('Selected page : ' + newPage + ', Previous page: ' + oldPage);
39 | }
40 |
41 | render () {
42 |
43 | return (
44 |
45 | Pager
46 | Pager based on ToolBox components with default button styles. Example: 1.
47 |
48 |
49 |
}
51 | nextButtonLabel={
}
52 | rangeLeftButtonLabel={
}
53 | rangeRightButtonLabel={
}
54 | totalPages={this.state.totalPages}
55 | currentPage={this.state.currentPage}
56 | visiblePagesBlockSize={this.props.visiblePagesBlockSize}
57 | onPageChange={this.onPageChange1}
58 | />
59 |
60 |
61 |
62 |
63 | Pager based on ToolBox components with custom button styles. Example: 2.
64 |
65 |
66 |
}
68 | nextButtonLabel={
}
69 | rangeLeftButtonLabel={
}
70 | rangeRightButtonLabel={
}
71 | leftRightArrowButtonStyles={{flat: true, primary: true}}
72 | leftRightRangeButtonStyles={{primary: true}}
73 | totalPages={this.state.totalPages}
74 | currentPage={this.state.currentPage}
75 | visiblePagesBlockSize={this.props.visiblePagesBlockSize}
76 | onPageChange={this.onPageChange2}
77 | />
78 |
79 |
80 |
81 |
82 | Pager based on ToolBox components with custom button styles. Example: 3.
83 |
84 |
85 |
}
87 | nextButtonLabel={
}
88 | rangeLeftButtonLabel={
}
89 | rangeRightButtonLabel={
}
90 | leftRightArrowButtonStyles={{ primary: true, raised: true }}
91 | leftRightRangeButtonStyles={{ raised: true}}
92 | pagesButtonStyles={{raised: true }}
93 | firstLastPagesButtonStyles={{ raised: true}}
94 | totalPages={this.state.totalPages}
95 | currentPage={this.state.currentPage}
96 | visiblePagesBlockSize={this.props.visiblePagesBlockSize}
97 | onPageChange={this.onPageChange2}
98 | />
99 |
100 |
101 |
102 |
103 | Pager based on ToolBox components with custom theme. Example: 4.
104 |
105 |
106 |
}
108 | nextButtonLabel={
}
109 | rangeLeftButtonLabel={
}
110 | rangeRightButtonLabel={
}
111 | leftRightArrowButtonStyles={{ primary: true, raised: true }}
112 | leftRightRangeButtonStyles={{ raised: true}}
113 | pagesButtonStyles={{raised: true }}
114 | firstLastPagesButtonStyles={{ raised: true}}
115 | totalPages={this.state.totalPages}
116 | currentPage={this.state.currentPage}
117 | visiblePagesBlockSize={this.props.visiblePagesBlockSize}
118 | onPageChange={this.onPageChange2}
119 | theme={style}
120 | />
121 |
122 |
123 |
124 |
125 |
126 | Pager based on ToolBox components with custom theme. Example: 5.
127 |
128 |
129 |
}
131 | nextButtonLabel={
}
132 | rangeLeftButtonLabel={
}
133 | rangeRightButtonLabel={
}
134 | leftRightArrowButtonStyles={{ primary: true}}
135 | firstLastPagesButtonStyles={{ raised: true}}
136 | totalPages={this.state.totalPages}
137 | currentPage={this.state.currentPage}
138 | visiblePagesBlockSize={this.props.visiblePagesBlockSize}
139 | onPageChange={this.onPageChange2}
140 | theme={style}
141 | />
142 |
143 |
144 |
145 |
150 |
151 |
152 | );
153 | }
154 | }
155 |
156 | export default PagerTest;
157 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Additions for React Toolbox library
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import 'babel-polyfill';
2 |
3 | import React from 'react';
4 | import ReactDOM from 'react-dom';
5 | import Root from './root';
6 |
7 | ReactDOM.render( , document.getElementById('app-root'));
8 |
--------------------------------------------------------------------------------
/example/root.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import {Card} from 'react-toolbox/lib/card';
4 |
5 | import Pager from './components/pager';
6 | import FilePicker from './components/filepicker';
7 | import Accordion from './components/accordion';
8 | import style from './style';
9 |
10 | const Root = () => (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | );
23 |
24 | export default Root;
25 |
--------------------------------------------------------------------------------
/example/style.scss:
--------------------------------------------------------------------------------
1 | $unit: 1rem !default;
2 |
3 | .card {
4 |
5 | box-sizing: border-box;
6 | padding: $unit * 2;
7 | margin-top: $unit * 0.75;
8 | background-color: #fff;
9 | border: 1px solid #f4f4f4;
10 |
11 | .pager {
12 | display: flex;
13 | flex-flow: row nowrap;
14 | justify-content: center;
15 | margin: 1rem 0 1.5rem 0;
16 |
17 | .active {
18 | text-decoration: none;
19 | color: #3f51b5;
20 | }
21 |
22 | .leftRightArrowButton{
23 | display: none;
24 | }
25 | }
26 |
27 | .accordion {
28 |
29 | .chord {
30 |
31 | border: 1px solid #f4f4f4;
32 |
33 | .label {
34 | border: none;
35 | }
36 |
37 | &.active {
38 | .label {
39 | border-bottom: 1px solid #f4f4f4;
40 | }
41 | }
42 |
43 | .content {
44 | margin-left: 10;
45 | margin-right: 10;
46 | }
47 | }
48 |
49 | }
50 |
51 | .accordion-body1 {
52 | display: flex;
53 | flex-flow: row nowrap;
54 | justify-content: space-around;
55 |
56 | > * {
57 | flex: 1;
58 | }
59 | }
60 |
61 | .accordion-body2 {
62 | padding: 1rem;
63 | padding-top: 0;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for react-toolbox-additions
2 |
3 | import { Pager } from "react-toolbox-additions/lib/pager";
4 | import { FilePicker } from "react-toolbox-additions/lib/filepicker";
5 |
6 | import { PagerTheme } from "react-toolbox-additions/lib/pager";
7 | import { FilePickerTheme } from "react-toolbox-additions/lib/filepicker";
8 |
9 | export {
10 | Peger,
11 | Autocomplete,
12 |
13 | PagerTheme,
14 | FilePickerTheme
15 | }
16 |
--------------------------------------------------------------------------------
/lib/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/commons";
2 |
3 | $indent: $unit *.5 !default;
4 | $button-margin: 0 $indent 0 0 !default;
5 |
6 | @mixin space-between {
7 | margin-right: $indent;
8 | }
9 |
--------------------------------------------------------------------------------
/lib/accordion/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/button/theme";
2 | @import "../config";
3 |
4 | $chord-content-padding: 1 * $unit !default;
5 | $chord-label-disabled-opacity: .2 !default;
6 | $chord-label-v-padding: 0.2 * $unit !default;
7 | $chord-label-height: 4.8 * $unit !default;
8 | $chord-icon-height: 2.4 * $unit !default;
9 | $chord-text-height: 1.4 * $unit !default;
10 | $chord-pointer-color: $color-primary !default;
11 | $chord-text: $color-black !default;
12 | $chord-text-color: $chord-text !default;
13 | $chord-text-inactive-color: rgba($chord-text, .7) !default;
14 |
--------------------------------------------------------------------------------
/lib/accordion/accordion.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.Accordion = exports.accordionFactory = undefined;
7 |
8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
9 |
10 | var _react = require('react');
11 |
12 | var _react2 = _interopRequireDefault(_react);
13 |
14 | var _classnames2 = require('classnames');
15 |
16 | var _classnames3 = _interopRequireDefault(_classnames2);
17 |
18 | var _reactCssThemr = require('react-css-themr');
19 |
20 | var _identifiers = require('../identifiers.js');
21 |
22 | var _chord = require('./chord.js');
23 |
24 | var _chord2 = _interopRequireDefault(_chord);
25 |
26 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27 |
28 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
29 |
30 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
31 |
32 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
33 |
34 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
35 |
36 | var factory = function factory(Chord) {
37 | var Accordion = function (_Component) {
38 | _inherits(Accordion, _Component);
39 |
40 | function Accordion() {
41 | _classCallCheck(this, Accordion);
42 |
43 | return _possibleConstructorReturn(this, (Accordion.__proto__ || Object.getPrototypeOf(Accordion)).apply(this, arguments));
44 | }
45 |
46 | _createClass(Accordion, [{
47 | key: 'handleHeaderClick',
48 |
49 |
50 | //events handler
51 | value: function handleHeaderClick(event, idx, item) {
52 | idx = parseInt(idx);
53 | if (this.props.onChange) {
54 | this.props.onChange(idx);
55 | }
56 | if (item.props.onClick) {
57 | item.props.onClick(event);
58 | }
59 | }
60 | }, {
61 | key: 'renderChords',
62 |
63 |
64 | //private methods
65 | value: function renderChords() {
66 | var _this2 = this;
67 |
68 | var chords = [];
69 | var idx = 0;
70 |
71 | _react2.default.Children.forEach(this.props.children, function (item) {
72 | if (item.type === Chord) {
73 | if (item.props.children) {
74 | chords.push(_react2.default.cloneElement(item, {
75 | id: idx,
76 | key: idx,
77 | theme: _this2.props.theme,
78 | active: _this2.props.index === idx,
79 | onClick: _this2.handleHeaderClick.bind(_this2, event, idx, item)
80 | }));
81 | ++idx;
82 | }
83 | }
84 | });
85 |
86 | return chords;
87 | }
88 | }, {
89 | key: 'render',
90 | value: function render() {
91 | var _props = this.props,
92 | className = _props.className,
93 | disableAnimation = _props.disableAnimation,
94 | theme = _props.theme;
95 |
96 | var classNames = (0, _classnames3.default)(theme.accordion, className, _defineProperty({}, theme.disableAnimation, disableAnimation));
97 |
98 | return _react2.default.createElement(
99 | 'div',
100 | { 'data-react-toolbox': 'accordion', className: classNames },
101 | _react2.default.createElement(
102 | 'div',
103 | { className: theme.accordion },
104 | this.renderChords()
105 | )
106 | );
107 | }
108 | }]);
109 |
110 | return Accordion;
111 | }(_react.Component);
112 |
113 | Accordion.propTypes = {
114 | children: _react.PropTypes.node,
115 | className: _react.PropTypes.string,
116 | disableAnimation: _react.PropTypes.bool,
117 | index: _react.PropTypes.number,
118 | onChange: _react.PropTypes.func,
119 | theme: _react.PropTypes.shape({
120 | accordion: _react.PropTypes.string
121 | })
122 | };
123 | Accordion.defaultProps = {
124 | index: 0,
125 | disableAnimation: false
126 | };
127 |
128 |
129 | return Accordion;
130 | };
131 |
132 | var Accordion = factory(_chord2.default);
133 | exports.default = (0, _reactCssThemr.themr)(_identifiers.ACCORDION)(Accordion);
134 | exports.accordionFactory = factory;
135 | exports.Accordion = Accordion;
--------------------------------------------------------------------------------
/lib/accordion/chord.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.Chord = undefined;
7 |
8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
9 |
10 | var _react = require('react');
11 |
12 | var _react2 = _interopRequireDefault(_react);
13 |
14 | var _reactDom = require('react-dom');
15 |
16 | var _reactDom2 = _interopRequireDefault(_reactDom);
17 |
18 | var _classnames5 = require('classnames');
19 |
20 | var _classnames6 = _interopRequireDefault(_classnames5);
21 |
22 | var _font_icon = require('react-toolbox/lib/font_icon');
23 |
24 | var _reactCssThemr = require('react-css-themr');
25 |
26 | var _identifiers = require('../identifiers.js');
27 |
28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29 |
30 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
31 |
32 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
33 |
34 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
35 |
36 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
37 |
38 | var contentId = 'contentId';
39 |
40 | var Chord = function (_Component) {
41 | _inherits(Chord, _Component);
42 |
43 | function Chord(props) {
44 | _classCallCheck(this, Chord);
45 |
46 | var _this = _possibleConstructorReturn(this, (Chord.__proto__ || Object.getPrototypeOf(Chord)).call(this));
47 |
48 | _this.state = {
49 | active: false
50 | };
51 |
52 | _this.handleClick = function (event) {
53 | if (!_this.props.disabled && _this.props.onClick) {
54 | _this.props.onClick(event);
55 | }
56 | };
57 |
58 | _this.handleResize = function () {
59 | if (_this.state.active) {
60 | _this.expand();
61 | } else {
62 | _this.collapse();
63 | }
64 | };
65 |
66 | _this.state.active = props.active;
67 | return _this;
68 | }
69 |
70 | _createClass(Chord, [{
71 | key: 'transitionEndEventName',
72 |
73 |
74 | //private methods
75 | value: function transitionEndEventName() {
76 | var i = void 0,
77 | undefined = void 0,
78 | el = document.createElement('div'),
79 | transitions = {
80 | 'transition': 'transitionend',
81 | 'OTransition': 'otransitionend',
82 | 'MozTransition': 'transitionend',
83 | 'WebkitTransition': 'webkitTransitionEnd'
84 | };
85 |
86 | for (i in transitions) {
87 | if (transitions.hasOwnProperty(i) && el.style[i] !== undefined) {
88 | return transitions[i];
89 | }
90 | }
91 | }
92 | }, {
93 | key: 'collapse',
94 | value: function collapse() {
95 | var contentEl = _reactDom2.default.findDOMNode(this.refs[contentId]);
96 | if (contentEl) {
97 | contentEl.style.height = getComputedStyle(contentEl).height;
98 | contentEl.offsetHeight;
99 | contentEl.style.height = 0;
100 | }
101 | }
102 | }, {
103 | key: 'expand',
104 | value: function expand() {
105 | var _this2 = this;
106 |
107 | var contentEl = _reactDom2.default.findDOMNode(this.refs[contentId]);
108 | if (contentEl) {
109 | (function () {
110 | var initialHeight = getComputedStyle(contentEl).height;
111 | contentEl.style.height = 'auto';
112 | var newHeight = getComputedStyle(contentEl).height;
113 | contentEl.style.height = initialHeight;
114 | contentEl.offsetHeight;
115 | contentEl.style.height = newHeight;
116 |
117 | var self = _this2;
118 | contentEl.addEventListener(_this2.transitionEndEventName(), function transitionEnd(event) {
119 | if (self.state.active) {
120 | contentEl.style.height = 'auto';
121 | }
122 | contentEl.removeEventListener(self.transitionEndEventName(), transitionEnd, false);
123 | }, false);
124 | })();
125 | }
126 | }
127 | }, {
128 | key: 'componentDidMount',
129 | value: function componentDidMount() {
130 | window.addEventListener('resize', this.handleResize);
131 | if (this.props.active) {
132 | this.expand();
133 | } else {
134 | this.collapse();
135 | }
136 | }
137 | }, {
138 | key: 'componentDidUpdate',
139 | value: function componentDidUpdate(prevProps) {
140 | if (!prevProps.active && this.props.active && this.props.onActive) {
141 | this.props.onActive();
142 | }
143 | }
144 | }, {
145 | key: 'componentWillReceiveProps',
146 | value: function componentWillReceiveProps(nextProps) {
147 | this.state.active = nextProps.active;
148 | if (this.state.active) {
149 | this.expand();
150 | } else {
151 | this.collapse();
152 | }
153 | }
154 | }, {
155 | key: 'componentWillUnmount',
156 | value: function componentWillUnmount() {
157 | window.removeEventListener('resize', this.handleResize);
158 | }
159 |
160 | //events handler
161 |
162 | }, {
163 | key: 'render',
164 | value: function render() {
165 | var _classnames;
166 |
167 | var _props = this.props,
168 | children = _props.children,
169 | id = _props.id,
170 | key = _props.key,
171 | active = _props.active,
172 | activeClassName = _props.activeClassName,
173 | className = _props.className,
174 | disabled = _props.disabled,
175 | hidden = _props.hidden,
176 | label = _props.label,
177 | labelIcon = _props.labelIcon,
178 | labelPostIcon = _props.labelPostIcon,
179 | theme = _props.theme;
180 |
181 | var _className = (0, _classnames6.default)(theme.label, (_classnames = {}, _defineProperty(_classnames, theme.withText, label), _defineProperty(_classnames, theme.withIcon, labelIcon), _defineProperty(_classnames, theme.withPostIcon, labelPostIcon), _classnames));
182 |
183 | var lIcon = labelIcon;
184 | if (lIcon && Object.prototype.toString.call(lIcon) !== '[object String]') {
185 | lIcon = _react2.default.cloneElement(labelIcon, {
186 | className: (0, _classnames6.default)(labelIcon.props.className, theme.icon)
187 | });
188 | } else if (labelIcon) {
189 | lIcon = _react2.default.createElement(_font_icon.FontIcon, { className: theme.icon, value: labelIcon });
190 | }
191 |
192 | var lpIcon = labelPostIcon;
193 | if (lpIcon && Object.prototype.toString.call(lpIcon) !== '[object String]') {
194 | lpIcon = _react2.default.cloneElement(labelPostIcon, {
195 | className: (0, _classnames6.default)(labelPostIcon.props.className, theme.postIcon)
196 | });
197 | } else if (labelPostIcon) {
198 | lpIcon = _react2.default.createElement(_font_icon.FontIcon, { className: theme.postIcon, value: labelPostIcon });
199 | }
200 |
201 | return _react2.default.createElement(
202 | 'div',
203 | { id: id, key: key, 'data-react-toolbox': 'chord', className: (0, _classnames6.default)(className, theme.chord, _defineProperty({}, theme.active, active), _defineProperty({}, theme.hidden, hidden), _defineProperty({}, theme.disabled, disabled)) },
204 | _react2.default.createElement(
205 | 'label',
206 | { className: _className, onClick: this.handleClick },
207 | lIcon,
208 | _react2.default.createElement(
209 | 'div',
210 | { className: theme.text },
211 | label
212 | ),
213 | lpIcon
214 | ),
215 | _react2.default.createElement(
216 | 'div',
217 | { ref: contentId, className: (0, _classnames6.default)(theme.content, !active ? theme.hidden : null) },
218 | children
219 | )
220 | );
221 | }
222 | }]);
223 |
224 | return Chord;
225 | }(_react.Component);
226 |
227 | Chord.propTypes = {
228 | active: _react.PropTypes.bool,
229 | activeClassName: _react.PropTypes.string,
230 | className: _react.PropTypes.string,
231 | disabled: _react.PropTypes.bool,
232 | hidden: _react.PropTypes.bool,
233 | label: _react.PropTypes.node,
234 | labelIcon: _react.PropTypes.node,
235 | labelPostIcon: _react.PropTypes.node,
236 | onActive: _react.PropTypes.func,
237 | onClick: _react.PropTypes.func,
238 | theme: _react.PropTypes.shape({
239 | active: _react.PropTypes.string,
240 | disabled: _react.PropTypes.string,
241 | hidden: _react.PropTypes.string,
242 | label: _react.PropTypes.string,
243 | content: _react.PropTypes.string
244 | })
245 | };
246 | Chord.defaultProps = {
247 | active: false,
248 | className: '',
249 | disabled: false,
250 | hidden: false
251 | };
252 | exports.default = (0, _reactCssThemr.themr)(_identifiers.CHORD)(Chord);
253 | exports.Chord = Chord;
--------------------------------------------------------------------------------
/lib/accordion/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ReactToolbox from "../index";
3 |
4 | export interface AccordionTheme {
5 | /**
6 | * Used for the root element.
7 | */
8 | accordion?: string;
9 | }
10 |
11 | interface AccordionProps extends ReactToolbox.Props {
12 | /**
13 | * The class(s) will be applied to the root elemt.
14 | */
15 | className
16 | /**
17 | * Children to pass through the component.
18 | */
19 | children?: React.ReactNode;
20 | /**
21 | * Disable the animation on children expanding/collapsing.
22 | * @default false
23 | */
24 | disableAnimation?: boolean;
25 | /**
26 | * Expanded element
27 | * @default 0
28 | */
29 | index?: number;
30 | /**
31 | * Callback function that is fired when the Chord changes.
32 | */
33 | onChange?: Function;
34 | /**
35 | * Classnames object defining the component style.
36 | */
37 | theme?: AccordionTheme;
38 | }
39 |
40 | export class Accordion extends React.Component { }
41 |
42 | export interface ChordTheme {
43 | /**
44 | * Added to the chord element (label and content) in case it's active.
45 | */
46 | active?: string;
47 | /**
48 | * Added to the chord element in case it's disabled.
49 | */
50 | disabled?: string;
51 | /**
52 | * Added to the chord element in case it's hidden.
53 | */
54 | hidden?: string;
55 | /**
56 | * Base style of header of chord element.
57 | */
58 | label?: string;
59 | /**
60 | * Base style of content of chord element.
61 | */
62 | content?: string;
63 | }
64 |
65 | interface ChordProps extends ReactToolbox.Props {
66 | /**
67 | * If true, the current component is visible.
68 | */
69 | active?: boolean;
70 | /**
71 | * Additional class name to provide custom styling for the active Chord.
72 | */
73 | activeClassName?: string;
74 | /**
75 | * If true, the current component is not clickable.
76 | * @default false
77 | */
78 | disabled?: boolean;
79 | /**
80 | * If true, the current component is not visible.
81 | * @default false
82 | */
83 | hidden?: boolean;
84 | /**
85 | * Label text for the chord header. Required.
86 | */
87 | label: string;
88 | /**
89 | * Icon for chord header. Required.
90 | */
91 | labelIcon: string;
92 | /**
93 | * Icon behind of the label for chord header.
94 | */
95 | labelPostIcon: string;
96 | /**
97 | * Callback function that is fired when the Chord is activated.
98 | */
99 | onActive?: Function;
100 | /**
101 | * Callback function that is fired when the chord label is clicked.
102 | */
103 | onClick?: Function;
104 | /**
105 | * Classnames object defining the component style.
106 | */
107 | theme?: ChordTheme;
108 | }
109 |
110 | export class Chord extends React.Component { }
111 |
--------------------------------------------------------------------------------
/lib/accordion/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.Accordion = exports.Chord = undefined;
7 |
8 | var _reactCssThemr = require('react-css-themr');
9 |
10 | var _identifiers = require('../identifiers.js');
11 |
12 | var _accordion = require('./accordion.js');
13 |
14 | var _chord = require('./chord.js');
15 |
16 | var _theme = require('./theme.scss');
17 |
18 | var _theme2 = _interopRequireDefault(_theme);
19 |
20 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21 |
22 | var applyTheme = function applyTheme(Component) {
23 | return (0, _reactCssThemr.themr)(_identifiers.ACCORDION, _theme2.default)(Component);
24 | };
25 | var ThemedChord = applyTheme(_chord.Chord);
26 | var ThemedAccordion = applyTheme((0, _accordion.accordionFactory)(ThemedChord));
27 |
28 | exports.Chord = ThemedChord;
29 | exports.Accordion = ThemedAccordion;
--------------------------------------------------------------------------------
/lib/accordion/theme.scss:
--------------------------------------------------------------------------------
1 | @import "./config";
2 |
3 | .accordion {
4 | position: relative;
5 | height: 100%;
6 | width: 100%;
7 | display: block;
8 |
9 | &.disableAnimation {
10 | .chord {
11 | .content {
12 | transition: none !important;
13 | }
14 | }
15 | }
16 |
17 | .chord {
18 | position: relative;
19 | width: 100%;
20 | display: block;
21 |
22 | &.hidden {
23 | display: none !important;
24 | }
25 |
26 | &.disabled {
27 | opacity: $chord-label-disabled-opacity;
28 | .label {
29 | cursor: default;
30 | }
31 | }
32 |
33 | .content {
34 | position: relative;
35 | height: 0;
36 | box-sizing: border-box;
37 | overflow: hidden;
38 | opacity: 0;
39 | transition: height $animation-duration ease-in-out, opacity $animation-duration linear;
40 | }
41 |
42 | &.active {
43 | margin-bottom: 2 * $chord-content-padding;
44 |
45 | .content {
46 | opacity: 1;
47 | height: auto;
48 | transition: height $animation-duration ease-in-out, opacity $animation-duration linear;
49 | }
50 |
51 | .label {
52 | color: $chord-pointer-color;
53 | margin-bottom: $chord-content-padding;
54 | }
55 | }
56 |
57 | .label {
58 | display: block;
59 | width: 100%;
60 | font-size: $chord-text-height;
61 | font-weight: $font-weight-semi-bold;
62 | padding-top: $chord-label-v-padding;
63 | padding-bottom: $chord-label-v-padding;
64 | margin-bottom: 0;
65 | color: $chord-text-color;
66 | text-transform: uppercase;
67 | transition-timing-function: $animation-curve-default;
68 | transition-duration: $animation-duration;
69 | transition-property: box-shadow, color;
70 | cursor: pointer;
71 |
72 | .text {
73 | position: relative;
74 | display: inline-block;
75 | height: $chord-icon-height;
76 | line-height: $chord-icon-height;
77 | vertical-align: top;
78 | margin-right: $chord-content-padding;
79 | }
80 |
81 | .icon,
82 | .postIcon {
83 | position: relative;
84 | display: inline-block;
85 | height: $chord-icon-height;
86 | width: $chord-icon-height;
87 | line-height: $chord-icon-height;
88 | }
89 |
90 | &.withIcon {
91 | }
92 |
93 | &.withPostButton {
94 | }
95 |
96 | &.withText {
97 | .icon {
98 | margin-right: $chord-content-padding;
99 | }
100 | }
101 |
102 | .postIcon {
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/lib/filepicker/_config.scss:
--------------------------------------------------------------------------------
1 | @import "../config";
2 |
3 | $input-min-width: $unit * 4 !default;
4 |
--------------------------------------------------------------------------------
/lib/filepicker/filepicker.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.FilePicker = exports.filePickerFactory = undefined;
7 |
8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
9 |
10 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
11 |
12 | var _react = require('react');
13 |
14 | var _react2 = _interopRequireDefault(_react);
15 |
16 | var _classnames = require('classnames');
17 |
18 | var _classnames2 = _interopRequireDefault(_classnames);
19 |
20 | var _reactCssThemr = require('react-css-themr');
21 |
22 | var _button = require('react-toolbox/lib/button');
23 |
24 | var _input = require('react-toolbox/lib/input');
25 |
26 | var _input2 = _interopRequireDefault(_input);
27 |
28 | var _identifiers = require('../identifiers.js');
29 |
30 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31 |
32 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
33 |
34 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
35 |
36 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
37 |
38 | var factory = function factory(Input, Button) {
39 | var FilePicker = function (_Component) {
40 | _inherits(FilePicker, _Component);
41 |
42 | function FilePicker(props) {
43 | _classCallCheck(this, FilePicker);
44 |
45 | var _this = _possibleConstructorReturn(this, (FilePicker.__proto__ || Object.getPrototypeOf(FilePicker)).call(this, props));
46 |
47 | _this.state = {
48 | value: _this.props.value
49 | };
50 |
51 | _this.handlerBrowse = function (e) {
52 | var files = e.target.files;
53 |
54 | if (files && files.length) {
55 | if (_this.state.value !== files[0].name) {
56 | if (_this.props.onChange) {
57 | _this.props.onChange(files[0], files[0].name);
58 | }
59 | }
60 |
61 | _this.setState({
62 | value: files[0].name
63 | });
64 | }
65 | };
66 |
67 | _this.state = { value: props.value };
68 | return _this;
69 | }
70 |
71 | _createClass(FilePicker, [{
72 | key: 'componentWillReceiveProps',
73 | value: function componentWillReceiveProps(nextProps) {
74 | if (this.state.value !== nextProps.value) {
75 | this.setState({
76 | value: nextProps.value
77 | });
78 | }
79 | }
80 | }, {
81 | key: 'render',
82 | value: function render() {
83 | var _props = this.props,
84 | className = _props.className,
85 | buttonProperties = _props.buttonProperties,
86 | inputProperties = _props.inputProperties,
87 | value = _props.value,
88 | inline = _props.inline,
89 | theme = _props.theme;
90 |
91 | var css = inline ? 'inline' : null;
92 |
93 | return _react2.default.createElement(
94 | 'div',
95 | { 'data-ext-react-toolbox': 'filepicker', className: (0, _classnames2.default)(theme.filepicker, className, [theme[css]]) },
96 | _react2.default.createElement(Input, _extends({
97 | className: (0, _classnames2.default)(theme.input),
98 | value: this.state.value
99 | }, inputProperties)),
100 | _react2.default.createElement(Button, _extends({
101 | className: (0, _classnames2.default)(theme.button, theme.iefix),
102 | onChange: this.handlerBrowse
103 | }, buttonProperties))
104 | );
105 | }
106 | }]);
107 |
108 | return FilePicker;
109 | }(_react.Component);
110 |
111 | FilePicker.propTypes = {
112 | buttonProperties: _react2.default.PropTypes.object,
113 | className: _react.PropTypes.string,
114 | inline: _react.PropTypes.bool,
115 | inputProperties: _react2.default.PropTypes.object,
116 | onChange: _react.PropTypes.func,
117 | theme: _react.PropTypes.shape({
118 | button: _react.PropTypes.string,
119 | filepicker: _react.PropTypes.string,
120 | inline: _react.PropTypes.string,
121 | input: _react.PropTypes.string
122 | }),
123 | value: _react.PropTypes.string
124 | };
125 | FilePicker.defaultProps = {
126 | buttonProperties: { label: 'BROWSE' },
127 | className: '',
128 | inline: false,
129 | inputProperties: { label: 'SELECT FILE' },
130 | value: undefined
131 | };
132 |
133 | return FilePicker;
134 | };
135 |
136 | var FilePicker = factory(_input2.default, _button.BrowseButton);
137 |
138 | exports.default = (0, _reactCssThemr.themr)(_identifiers.FILEPICKER)(FilePicker);
139 | exports.filePickerFactory = factory;
140 | exports.FilePicker = FilePicker;
--------------------------------------------------------------------------------
/lib/filepicker/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ReactToolbox from "react-toolbox/lib/index";
3 |
4 | export interface FilePickerTheme {
5 | /**
6 | * Used for the root element.
7 | */
8 | filepicker?: string;
9 | /**
10 | * Used for the input component.
11 | */
12 | input?: string;
13 | /**
14 | * Used for inline style of component.
15 | */
16 | inline?: string;
17 | /**
18 | * Used for the button component.
19 | */
20 | button?: string;
21 | }
22 |
23 | interface FilePickerProps extends ReactToolbox.Props {
24 | /**
25 | * This class will be applied to the root elemt.
26 | */
27 | className?: string;
28 | /**
29 | * This is button base properties like: accent, disabled, icon, ...
30 | */
31 | buttonProperties?: object
32 | /**
33 | * This is input base properties like: hint, disabled, icon, ...
34 | */
35 | inputProperties?: object
36 | /**
37 | * If true, the component will apear inline.
38 | * @default false
39 | */
40 | inline?: boolean
41 | /**
42 | * Callback called when the input is changing.
43 | */
44 | onChange?: Function;
45 | /**
46 | * Classnames object defining the component style.
47 | */
48 | theme?: FilePickerTheme;
49 | /**
50 | * This is initial value of input component.
51 | */
52 | value?: string
53 | }
54 |
55 | export class FilePicker extends React.Component { }
56 |
57 | export default FilePicker;
58 |
--------------------------------------------------------------------------------
/lib/filepicker/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.FilePicker = undefined;
7 |
8 | var _reactCssThemr = require('react-css-themr');
9 |
10 | var _identifiers = require('../identifiers.js');
11 |
12 | var _filepicker = require('./filepicker.js');
13 |
14 | var _button = require('react-toolbox/lib/button');
15 |
16 | var _input = require('react-toolbox/lib/input');
17 |
18 | var _theme = require('./theme.scss');
19 |
20 | var _theme2 = _interopRequireDefault(_theme);
21 |
22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23 |
24 | var FilePicker = (0, _filepicker.filePickerFactory)(_input.Input, _button.BrowseButton);
25 |
26 | var ThemedFilePicker = (0, _reactCssThemr.themr)(_identifiers.FILEPICKER, _theme2.default)(FilePicker);
27 | exports.default = ThemedFilePicker;
28 | exports.FilePicker = ThemedFilePicker;
--------------------------------------------------------------------------------
/lib/filepicker/theme.scss:
--------------------------------------------------------------------------------
1 | @import "./config";
2 |
3 | .filepicker {
4 |
5 | > * {
6 | display: inline-block;
7 | vertical-align: middle;
8 | }
9 |
10 | &.inline {
11 | display: inline-block;
12 | vertical-align: middle;
13 | }
14 |
15 | .input {
16 | @include space-between;
17 | min-width: $input-min-width;
18 |
19 | & span:last-child {
20 | opacity: 1 !important;
21 | }
22 | }
23 |
24 | /*ie fix*/
25 | .iefix {
26 | input {
27 | top: 0 !important;
28 | left: 0 !important;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/identifiers.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | var ACCORDION = exports.ACCORDION = 'ERTAccordion';
7 | var CHORD = exports.CHORD = 'ERTChord';
8 | var PAGER = exports.PAGER = 'ERTPager';
9 | var FILEPICKER = exports.FILEPICKER = 'ERTFilePicker';
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.FilePicker = exports.Pager = undefined;
7 |
8 | var _accordion = require('./accordion');
9 |
10 | Object.keys(_accordion).forEach(function (key) {
11 | if (key === "default" || key === "__esModule") return;
12 | Object.defineProperty(exports, key, {
13 | enumerable: true,
14 | get: function get() {
15 | return _accordion[key];
16 | }
17 | });
18 | });
19 |
20 | var _pager = require('./pager');
21 |
22 | var _pager2 = _interopRequireDefault(_pager);
23 |
24 | var _filepicker = require('./filepicker');
25 |
26 | var _filepicker2 = _interopRequireDefault(_filepicker);
27 |
28 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29 |
30 | exports.Pager = _pager2.default;
31 | exports.FilePicker = _filepicker2.default;
--------------------------------------------------------------------------------
/lib/pager/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/button/theme";
2 | @import "../config";
3 |
--------------------------------------------------------------------------------
/lib/pager/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ReactToolbox from "react-toolbox/lib/index";
3 |
4 | export interface PagerTheme {
5 | /**
6 | * Used for the root element.
7 | */
8 | pager?: string;
9 | /**
10 | * Used for the active page.
11 | */
12 | active?: string;
13 | /**
14 | * Used for the first and last page buttons.
15 | */
16 | firstLastPagesButton?: string;
17 | /**
18 | * Used for the next and previous arrow buttons.
19 | */
20 | leftRightArrowButton?: string;
21 | /**
22 | * Used for the next and previous range pages buttons.
23 | */
24 | leftRightRangeButton?: string;
25 | /**
26 | * Used for the regular page buttons.
27 | */
28 | pagesButton?: string;
29 | }
30 |
31 | interface PagerProps extends ReactToolbox.Props {
32 | /**
33 | * Used for the previous button content.
34 | */
35 | prevButtonLabel?: string;
36 | /**
37 | * Used for the left range button content
38 | */
39 | rangeLeftButtonLabel?: string;
40 | /**
41 | * Used for the right range button content
42 | */
43 | rangeRightButtonLabel?: string;
44 | /**
45 | * Used for the next button content
46 | */
47 | nextButtonLabel?: string;
48 | /**
49 | * A Number with the currently selected page
50 | */
51 | currentPage?: number;
52 | /**
53 | * A Number of total pages.
54 | */
55 | totalPages?: number;
56 | /**
57 | * A Number of pages visible in control except next, previous and ranges buttons, the minimum value is 2.
58 | */
59 | visiblePagesBlockSize?: number;
60 | /**
61 | * Callback called when the page is changing.
62 | */
63 | onPageChange?: Function;
64 | /**
65 | * Classnames object defining the component style.
66 | */
67 | theme?: PagerTheme;
68 | /**
69 | * This class will be applied to the root elemt.
70 | */
71 | pagerClassName?: string;
72 | /**
73 | * Defining default style of first, last page buttons.
74 | * it can have following styles:
75 | * accent,
76 | * flat,
77 | * inverse,
78 | * mini,
79 | * neutral,
80 | * primary,
81 | * raised,
82 | * toggle
83 | */
84 | firstLastPagesButtonStyles?: object;
85 | /**
86 | * Defining default style of next, previous buttons.
87 | * it can have following styles:
88 | * accent,
89 | * flat,
90 | * inverse,
91 | * mini,
92 | * neutral,
93 | * primary,
94 | * raised,
95 | * toggle
96 | */
97 | leftRightArrowButtonStyles?: object;
98 | /**
99 | * Defining default style of left, right range buttons.
100 | * it can have following styles:
101 | * accent,
102 | * flat,
103 | * inverse,
104 | * mini,
105 | * neutral,
106 | * primary,
107 | * raised,
108 | * toggle
109 | */
110 | leftRightRangeButtonStyles?: object;
111 | /**
112 | * Defining default style of regular page buttons.
113 | * it can have following styles:
114 | * accent,
115 | * flat,
116 | * inverse,
117 | * mini,
118 | * neutral,
119 | * primary,
120 | * raised,
121 | * toggle
122 | */
123 | pagesButtonStyles?: object;
124 | }
125 |
126 | export class Pager extends React.Component { }
127 |
128 | export default Pager;
129 |
--------------------------------------------------------------------------------
/lib/pager/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.Pager = undefined;
7 |
8 | var _reactCssThemr = require('react-css-themr');
9 |
10 | var _identifiers = require('../identifiers.js');
11 |
12 | var _pager = require('./pager.js');
13 |
14 | var _page = require('./page.js');
15 |
16 | var _page2 = _interopRequireDefault(_page);
17 |
18 | var _theme = require('./theme.scss');
19 |
20 | var _theme2 = _interopRequireDefault(_theme);
21 |
22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
23 |
24 | var Pager = (0, _pager.pagerFactory)(_page2.default);
25 |
26 | var ThemedPager = (0, _reactCssThemr.themr)(_identifiers.PAGER, _theme2.default)(Pager);
27 | exports.default = ThemedPager;
28 | exports.Pager = ThemedPager;
--------------------------------------------------------------------------------
/lib/pager/page.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.BUTTON_TYPE = undefined;
7 |
8 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
9 |
10 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
11 |
12 | var _react = require('react');
13 |
14 | var _react2 = _interopRequireDefault(_react);
15 |
16 | var _classnames = require('classnames');
17 |
18 | var _classnames2 = _interopRequireDefault(_classnames);
19 |
20 | var _button = require('react-toolbox/lib/button');
21 |
22 | var _button2 = _interopRequireDefault(_button);
23 |
24 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25 |
26 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
27 |
28 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
29 |
30 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
31 |
32 | var BUTTON_TYPE = exports.BUTTON_TYPE = {
33 | PAGE: 0,
34 | RANGE: 1,
35 | ARROW: 2
36 | };
37 |
38 | var Page = function (_Component) {
39 | _inherits(Page, _Component);
40 |
41 | function Page(props) {
42 | _classCallCheck(this, Page);
43 |
44 | var _this = _possibleConstructorReturn(this, (Page.__proto__ || Object.getPrototypeOf(Page)).call(this));
45 |
46 | _this.state = {
47 | disabled: false,
48 | active: false,
49 | data: 0,
50 | buttonType: 0,
51 | label: null
52 | };
53 |
54 |
55 | _this.state.data = props.data;
56 | _this.state.buttonType = props.buttonType;
57 | _this.state.label = props.children;
58 | return _this;
59 | }
60 |
61 | _createClass(Page, [{
62 | key: 'componentWillReceiveProps',
63 | value: function componentWillReceiveProps(nextProps) {
64 | if (nextProps.children && !isNaN(nextProps.children) && this.state.label !== nextProps.children) {
65 | this.setState({
66 | label: nextProps.children
67 | });
68 | }
69 | if (nextProps.buttonType && !isNaN(nextProps.buttonType) && this.state.buttonType !== nextProps.buttonType) {
70 | this.setState({
71 | buttonType: nextProps.buttonType
72 | });
73 | }
74 | }
75 |
76 | //events handlers
77 |
78 | }, {
79 | key: 'handlerClick',
80 | value: function handlerClick() {
81 | if (this.props.onPageClick) {
82 | this.props.onPageClick(this.state.data, this.state.buttonType);
83 | }
84 | }
85 |
86 | //rendering
87 |
88 | }, {
89 | key: 'render',
90 | value: function render() {
91 | var styles = this.props.buttonStyles[this.state.buttonType];
92 | var className = this.props.buttonClassNames[this.state.buttonType];
93 |
94 | if (styles['disabled'] === undefined) {
95 | styles = _extends({}, styles, { disabled: this.state.disabled });
96 | } else {
97 | styles['disabled'] = this.state.disabled;
98 | }
99 |
100 | return _react2.default.createElement(
101 | _button2.default,
102 | _extends({
103 | className: (0, _classnames2.default)(className, this.state.active ? this.props.activeClassName : null),
104 | onClick: this.handlerClick.bind(this)
105 | }, styles),
106 | this.state.label
107 | );
108 | }
109 |
110 | //public methods
111 |
112 | }, {
113 | key: 'update',
114 | value: function update(active, data, label, type) {
115 | this.setState({
116 | active: active,
117 | data: data,
118 | buttonType: type,
119 | label: label
120 | });
121 | }
122 | }, {
123 | key: 'disable',
124 | value: function disable(v) {
125 | this.setState({
126 | disabled: v
127 | });
128 | }
129 | }]);
130 |
131 | return Page;
132 | }(_react.Component);
133 |
134 | Page.propTypes = {
135 | activeClassName: _react.PropTypes.string,
136 | buttonClassNames: _react.PropTypes.object,
137 | buttonStyles: _react.PropTypes.object,
138 | buttonType: _react.PropTypes.oneOf([BUTTON_TYPE.PAGE, BUTTON_TYPE.RANGE, BUTTON_TYPE.ARROW]),
139 | onPageClick: _react.PropTypes.func
140 | };
141 | Page.defaultProps = {
142 | buttonType: 0,
143 | buttonStyles: { 0: { flat: true } },
144 | buttonClassNames: { 0: null }
145 | };
146 | exports.default = Page;
--------------------------------------------------------------------------------
/lib/pager/pager.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | exports.Pager = exports.pagerFactory = undefined;
7 |
8 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
9 |
10 | var _react = require('react');
11 |
12 | var _react2 = _interopRequireDefault(_react);
13 |
14 | var _classnames = require('classnames');
15 |
16 | var _classnames2 = _interopRequireDefault(_classnames);
17 |
18 | var _reactCssThemr = require('react-css-themr');
19 |
20 | var _page = require('./page.js');
21 |
22 | var _page2 = _interopRequireDefault(_page);
23 |
24 | var _identifiers = require('../identifiers.js');
25 |
26 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
27 |
28 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
29 |
30 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
31 |
32 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
33 |
34 | var isOnePage = function isOnePage(first, last) {
35 | return first === last || !last;
36 | };
37 |
38 | var isBorderPage = function isBorderPage(curr, border) {
39 | return curr === border;
40 | };
41 |
42 | var clone = function clone(src) {
43 | return JSON.parse(JSON.stringify(src));
44 | };
45 |
46 | var prevPageId = 'prev';
47 | var nextPageId = 'next';
48 |
49 | var initialVisiblePagesBlockSize = 3;
50 | var initialCurrentPage = 1;
51 | var first = 1;
52 | /*
53 | * adjustment of start and end elements at range to have equal elements during navigation
54 | * 2 - because we already have the rendered first and last button
55 | */
56 | var adjustment = 2;
57 |
58 | var factory = function factory(Page) {
59 | var Pager = function (_Component) {
60 | _inherits(Pager, _Component);
61 |
62 | function Pager(props) {
63 | _classCallCheck(this, Pager);
64 |
65 | var _this = _possibleConstructorReturn(this, (Pager.__proto__ || Object.getPrototypeOf(Pager)).call(this));
66 |
67 | _this._ranges = {
68 | leftEnd: null,
69 | rightStart: null
70 | };
71 | _this._pages = [];
72 | _this.state = {
73 | currentPage: initialCurrentPage,
74 | totalPages: initialCurrentPage
75 | };
76 |
77 |
78 | if (props) {
79 | _this.state.currentPage = props.currentPage;
80 | _this.state.totalPages = props.totalPages;
81 | }
82 | return _this;
83 | }
84 |
85 | //fields
86 |
87 |
88 | _createClass(Pager, [{
89 | key: 'componentWillReceiveProps',
90 | value: function componentWillReceiveProps(nextProps) {
91 | if (nextProps.currentPage && !isNaN(Number(nextProps.currentPage)) && this.state.currentPage !== nextProps.currentPage) {
92 | this._pages.splice(0);
93 | this.setState({
94 | currentPage: Number(nextProps.currentPage < first ? first : nextProps.currentPage)
95 | });
96 | }
97 | if (nextProps.totalPages && !isNaN(Number(nextProps.totalPages)) && this.state.totalPages !== nextProps.totalPages) {
98 | this._pages.splice(0);
99 | this.setState({
100 | totalPages: Number(nextProps.totalPages < first ? first : nextProps.totalPages)
101 | });
102 | }
103 | if (nextProps.visiblePagesBlockSize && !isNaN(Number(nextProps.visiblePagesBlockSize)) && this.state.visiblePagesBlockSize !== nextProps.visiblePagesBlockSize) {
104 | this._pages.splice(0);
105 | this.setState({
106 | visiblePagesBlockSize: Number(nextProps.visiblePagesBlockSize < nextProps.totalPages ? nextProps.visiblePagesBlockSize : nextProps.totalPages)
107 | });
108 | }
109 | }
110 | }, {
111 | key: 'componentWillUnmount',
112 | value: function componentWillUnmount() {
113 | this._pages.splice(0);
114 | }
115 | }, {
116 | key: 'componentDidMount',
117 | value: function componentDidMount() {
118 | this.updateState(this.state.currentPage, this.state.totalPages);
119 | }
120 | }, {
121 | key: 'componentDidUpdate',
122 | value: function componentDidUpdate() {
123 | this.updatePages(this.state.currentPage, this.state.totalPages);
124 | }
125 |
126 | //events handlers
127 |
128 | }, {
129 | key: 'handlerPageClick',
130 | value: function handlerPageClick(page, type) {
131 | if (type === _page.BUTTON_TYPE.RANGE) {
132 | this.handlerRangeClick(page);
133 | return;
134 | }
135 |
136 | var oldValue = this.state.currentPage;
137 | var newValue = page;
138 |
139 | this.updateState(newValue);
140 |
141 | if (this.props.onPageChange) {
142 | this.props.onPageChange(newValue, oldValue);
143 | }
144 | }
145 | }, {
146 | key: 'handlerRangeClick',
147 | value: function handlerRangeClick(key) {
148 | var curr = this.state.currentPage;
149 | var last = this.state.totalPages;
150 |
151 | var right = !this._ranges.rightStart ? last : this._ranges.rightStart;
152 | var left = !this._ranges.leftEnd ? first : this._ranges.leftEnd;
153 |
154 | var newValue = curr;
155 | var sum = first + left;
156 | if (key === prevPageId) {
157 | newValue = sum >> 1; //rounding to left
158 | } else {
159 | sum = last + right;
160 | newValue = (sum >> 1) + sum % 2; //rounding to right
161 | }
162 |
163 | this.updateState(newValue);
164 |
165 | if (this.props.onPageChange) {
166 | this.props.onPageChange(newValue, curr);
167 | }
168 | }
169 | }, {
170 | key: 'handlerPrevNextClick',
171 | value: function handlerPrevNextClick(key, type) {
172 | var oldValue = this.state.currentPage;
173 | var newValue = key === prevPageId ? oldValue - 1 : oldValue + 1;
174 |
175 | this.updateState(newValue);
176 |
177 | if (this.props.onPageChange) {
178 | this.props.onPageChange(newValue, oldValue);
179 | }
180 | }
181 |
182 | //private methods
183 |
184 | }, {
185 | key: 'updateState',
186 | value: function updateState(newValue) {
187 | this.state.currentPage = newValue;
188 |
189 | if (this._pages.length > 0) {
190 | this.updatePages(newValue, this.state.totalPages);
191 | } else {
192 | this.forceUpdate();
193 | }
194 | }
195 | }, {
196 | key: 'updatePages',
197 | value: function updatePages(currPage, totalPages) {
198 | var curr = currPage;
199 | var last = totalPages;
200 |
201 | var blockSize = this.props.visiblePagesBlockSize === 1 ? adjustment : this.props.visiblePagesBlockSize;
202 |
203 | var padding = blockSize >> 1;
204 | var left = curr - padding * (blockSize % 2); //in case of even visiblePagesBlockSize
205 | var right = curr + padding;
206 |
207 | var blocksNumber = Math.ceil(last / blockSize);
208 | var currentBlock = Math.ceil(curr / blockSize);
209 |
210 | var start = (currentBlock - 1) * blockSize + first;
211 | var end = start + blockSize - first;
212 |
213 | if (currentBlock === 1) {
214 | //adjust set of buttons if current is on the left boundary
215 | end += adjustment;
216 | end = last - first === end ? last : end;
217 | } else if (currentBlock < blocksNumber) {
218 | //adjustment set of buttons if current is between boundaries
219 | start = left;
220 | end = right;
221 |
222 | currentBlock = Math.ceil((totalPages - end === 1 ? totalPages : end) / blockSize);
223 | }
224 |
225 | if (currentBlock === blocksNumber) {
226 | //adjustment set of buttons if current is on the right boundary
227 | start = last - (blockSize + adjustment - first);
228 | start = start - 1 <= first ? first : start;
229 | end = last;
230 | }
231 |
232 | this.refs[prevPageId].disable(curr === first);
233 |
234 | var buttonIdx = 0;
235 |
236 | if (currentBlock > 1 && start - 1 > first) {
237 | this.refs[buttonIdx].update(curr === first, first, String(first), _page.BUTTON_TYPE.FLPAGE);
238 | ++buttonIdx;
239 |
240 | this.refs[buttonIdx].update(false, prevPageId, this.props.rangeLeftButtonLabel, _page.BUTTON_TYPE.RANGE);
241 | ++buttonIdx;
242 | }
243 |
244 | for (var i = start; i <= last && i <= end; ++i) {
245 | var bType = _page.BUTTON_TYPE.PAGE;
246 | if (i === first || i === last) {
247 | bType = _page.BUTTON_TYPE.FLPAGE;
248 | }
249 | this.refs[buttonIdx].update(curr === i, i, String(i), bType);
250 | ++buttonIdx;
251 | }
252 |
253 | if (currentBlock < blocksNumber && end < last) {
254 | this.refs[buttonIdx].update(false, nextPageId, this.props.rangeRightButtonLabel, _page.BUTTON_TYPE.RANGE);
255 | ++buttonIdx;
256 |
257 | this.refs[buttonIdx].update(curr === last, last, String(last), _page.BUTTON_TYPE.FLPAGE);
258 | ++buttonIdx;
259 | }
260 |
261 | this.refs[nextPageId].disable(curr === last);
262 |
263 | // keep range boundaries to calculate correct navigation through the range
264 | this._ranges.leftEnd = start;
265 | this._ranges.rightStart = end - 1;
266 | }
267 |
268 | //rendering
269 |
270 | }, {
271 | key: 'renderPages',
272 | value: function renderPages(currPage, totalPages) {
273 | this._pages.splice(0);
274 |
275 | var curr = currPage;
276 | var last = totalPages < first ? first : totalPages;
277 | if (curr < first || curr > last) {
278 | curr = curr < first ? first : curr > last ? last : curr;
279 | this.setState({
280 | currentPage: curr
281 | });
282 | }
283 |
284 | var content = [];
285 |
286 | var buttonsCount = this.props.visiblePagesBlockSize + adjustment + 2;
287 | buttonsCount = buttonsCount > last ? last : buttonsCount;
288 |
289 | var possibleButtonClassNames = {};
290 | possibleButtonClassNames[_page.BUTTON_TYPE.FLPAGE] = (0, _classnames2.default)(this.props.theme.firstLastPagesButton);
291 | possibleButtonClassNames[_page.BUTTON_TYPE.PAGE] = (0, _classnames2.default)(this.props.theme.pagesButton);
292 | possibleButtonClassNames[_page.BUTTON_TYPE.RANGE] = (0, _classnames2.default)(this.props.theme.leftRightRangeButton);
293 | possibleButtonClassNames[_page.BUTTON_TYPE.ARROW] = (0, _classnames2.default)(this.props.theme.leftRightArrowButton);
294 |
295 | var possibleLeftButtoStyles = {};
296 | possibleLeftButtoStyles[_page.BUTTON_TYPE.ARROW] = clone(this.props.leftRightArrowButtonStyles);
297 | possibleLeftButtoStyles[_page.BUTTON_TYPE.ARROW].disabled = isOnePage(first, this.state.totalPages) || isBorderPage(this.state.currentPage, first);
298 | content.push(_react2.default.createElement(
299 | Page,
300 | {
301 | key: prevPageId,
302 | ref: prevPageId,
303 | data: prevPageId,
304 | buttonType: _page.BUTTON_TYPE.ARROW,
305 | buttonStyles: possibleLeftButtoStyles,
306 | buttonClassNames: possibleButtonClassNames,
307 | onPageClick: this.handlerPrevNextClick.bind(this) },
308 | this.props.prevButtonLabel
309 | ));
310 |
311 | var possibleButtoStyles = {};
312 | possibleButtoStyles[_page.BUTTON_TYPE.FLPAGE] = this.props.firstLastPagesButtonStyles;
313 | possibleButtoStyles[_page.BUTTON_TYPE.PAGE] = this.props.pagesButtonStyles;
314 | possibleButtoStyles[_page.BUTTON_TYPE.RANGE] = this.props.leftRightRangeButtonStyles;
315 | for (var i = 0; i < buttonsCount; ++i) {
316 | content.push(_react2.default.createElement(
317 | Page,
318 | {
319 | key: i,
320 | ref: i,
321 | data: i,
322 | buttonType: _page.BUTTON_TYPE.PAGE,
323 | activeClassName: (0, _classnames2.default)(this.props.theme.active),
324 | buttonClassNames: possibleButtonClassNames,
325 | onPageClick: this.handlerPageClick.bind(this),
326 | buttonStyles: possibleButtoStyles
327 | },
328 | String(i)
329 | ));
330 | this._pages.push(i);
331 | }
332 |
333 | var possibleRightButtoStyles = {};
334 | possibleRightButtoStyles[_page.BUTTON_TYPE.ARROW] = clone(this.props.leftRightArrowButtonStyles);
335 | possibleRightButtoStyles[_page.BUTTON_TYPE.ARROW].disabled = isOnePage(first, this.state.totalPages) || isBorderPage(this.state.currentPage, this.state.totalPages);
336 | content.push(_react2.default.createElement(
337 | Page,
338 | {
339 | key: nextPageId,
340 | ref: nextPageId,
341 | data: nextPageId,
342 | buttonType: _page.BUTTON_TYPE.ARROW,
343 | buttonStyles: possibleLeftButtoStyles,
344 | buttonClassNames: possibleButtonClassNames,
345 | onPageClick: this.handlerPrevNextClick.bind(this) },
346 | this.props.nextButtonLabel
347 | ));
348 |
349 | return content;
350 | }
351 | }, {
352 | key: 'render',
353 | value: function render() {
354 | return _react2.default.createElement(
355 | 'div',
356 | { 'data-ext-react-toolbox': 'pager', className: (0, _classnames2.default)(this.props.theme.pager, this.props.pagerClassName) },
357 | this.renderPages(this.state.currentPage, this.state.totalPages)
358 | );
359 | }
360 | }]);
361 |
362 | return Pager;
363 | }(_react.Component);
364 |
365 | Pager.propTypes = {
366 | currentPage: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.number]).isRequired,
367 | firstLastPagesButtonStyles: _react.PropTypes.object,
368 | leftRightArrowButtonStyles: _react.PropTypes.object,
369 | leftRightRangeButtonStyles: _react.PropTypes.object,
370 | nextButtonLabel: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.element]),
371 | onPageChange: _react.PropTypes.func,
372 | pagerClassName: _react.PropTypes.string,
373 | pagesButtonStyles: _react.PropTypes.object,
374 | prevButtonLabel: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.element]),
375 | rangeLeftButtonLabel: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.element]),
376 | rangeRightButtonLabel: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.element]),
377 | theme: _react.PropTypes.shape({
378 | pager: _react.PropTypes.string,
379 | active: _react.PropTypes.string,
380 | firstLastPagesButton: _react.PropTypes.string,
381 | leftRightArrowButton: _react.PropTypes.string,
382 | leftRightRangeButton: _react.PropTypes.string,
383 | pagesButton: _react.PropTypes.string
384 | }),
385 | totalPages: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.number]).isRequired,
386 | visiblePagesBlockSize: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.number]).isRequired
387 | };
388 | Pager.defaultProps = {
389 | currentPage: initialCurrentPage,
390 | totalPages: initialCurrentPage,
391 | firstLastPagesButtonStyles: { flat: true },
392 | leftRightArrowButtonStyles: { raised: true },
393 | leftRightRangeButtonStyles: { flat: true },
394 | nextButtonLabel: '>',
395 | pagesButtonStyles: { flat: true },
396 | prevButtonLabel: '<',
397 | rangeLeftButtonLabel: '...',
398 | rangeRightButtonLabel: '...',
399 | visiblePagesBlockSize: initialVisiblePagesBlockSize
400 | };
401 |
402 |
403 | return Pager;
404 | };
405 |
406 | var Pager = factory(_page2.default);
407 |
408 | exports.default = (0, _reactCssThemr.themr)(_identifiers.PAGER)(Pager);
409 | exports.pagerFactory = factory;
410 | exports.Pager = Pager;
--------------------------------------------------------------------------------
/lib/pager/theme.scss:
--------------------------------------------------------------------------------
1 | @import "./config";
2 |
3 | .pager {
4 | display: inline-block;
5 | vertical-align: middle;
6 |
7 | .firstLastPagesButton,
8 | .leftRightArrowButton,
9 | .leftRightRangeButton,
10 | .pagesButton {
11 | min-width: $button-height;
12 | margin: $button-margin;
13 | }
14 |
15 | .active {
16 | text-decoration: underline;
17 | }
18 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-toolbox-additions",
3 | "description": "The project provides additions for react-toolbox which are not defined at material design and therefore were not included to original react-toolbox components library.",
4 | "homepage": "https://github.com/MaximKomlev/react-toolbox-additions",
5 | "version": "1.3.9",
6 | "main": "./lib",
7 | "author": {
8 | "name": "Maksim Komleu",
9 | "url": "https://github.com/MaximKomlev/react-toolbox-additions"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/MaximKomlev/react-toolbox-additions.git"
14 | },
15 | "bugs": {
16 | "email": "max_komlev@msn.com"
17 | },
18 | "keywords": [
19 | "components",
20 | "react-toolbox",
21 | "react",
22 | "react-component",
23 | "toolkit",
24 | "addons",
25 | "pager",
26 | "filepicker",
27 | "accordion"
28 | ],
29 | "dependencies": {
30 | "classnames": "~2.2.5",
31 | "core-js": "~2.4.0",
32 | "react": "~15.4.0",
33 | "react-css-themr": "^1.6.0",
34 | "react-dom": "^15.4.0",
35 | "react-toolbox": "^1.3.2"
36 | },
37 | "devDependencies": {
38 | "autoprefixer": "~6.4.0",
39 | "babel-cli": "~6.8.0",
40 | "babel-core": "~6.13.2",
41 | "babel-eslint": "~6.0.4",
42 | "babel-loader": "~6.2.4",
43 | "babel-plugin-react-transform": "~2.0.2",
44 | "babel-polyfill": "~6.13.0",
45 | "babel-preset-es2015": "~6.13.2",
46 | "babel-preset-react": "~6.5.0",
47 | "babel-preset-stage-0": "~6.5.0",
48 | "bluebird": "~3.3.5",
49 | "cpx": "~1.3.1",
50 | "cross-env": "~2.0.0",
51 | "css-loader": "~0.23.1",
52 | "eslint": "~3.2.2",
53 | "eslint-plugin-babel": "~3.2.0",
54 | "eslint-plugin-react": "~6.0.0",
55 | "expect": "~1.20.1",
56 | "express": "~4.13.4",
57 | "extract-text-webpack-plugin": "~1.0.1",
58 | "git-dirty": "~1.0.2",
59 | "glob": "~7.0.3",
60 | "immutability-helper": "~2.0.0",
61 | "karma": "~1.1.2",
62 | "karma-chrome-launcher": "~1.0.1",
63 | "karma-cli": "~1.0.0",
64 | "karma-mocha": "~1.0.1",
65 | "karma-phantomjs-launcher": "~1.0.0",
66 | "karma-webpack": "~1.7.0",
67 | "mocha": "~3.0.1",
68 | "node-sass": "~3.7.0",
69 | "phantomjs": "~2.1.7",
70 | "phantomjs-polyfill": "0.0.2",
71 | "phantomjs-prebuilt": "~2.1.7",
72 | "postcss-loader": "~0.9.1",
73 | "react": "~15.3.0",
74 | "react-addons-css-transition-group": "~15.3.0",
75 | "react-addons-test-utils": "~15.3.0",
76 | "react-docgen": "~2.8.2",
77 | "react-dom": "~15.3.0",
78 | "react-transform-catch-errors": "~1.0.2",
79 | "react-transform-hmr": "~1.0.4",
80 | "redbox-react": "~1.2.4",
81 | "rimraf": "~2.5.2",
82 | "sass-lint": "1.8.2",
83 | "sass-loader": "~4.0.0",
84 | "sinon": "git://github.com/sinonjs/sinon.git#b672042043517b9f84e14ed0fb8265126168778a",
85 | "style-loader": "~0.13.1",
86 | "webpack": "~1.13.0",
87 | "html-webpack-plugin": "~2.18.0",
88 | "webpack-dev-server": "~1.14.1"
89 | },
90 | "scripts": {
91 | "build": "cross-env NODE_ENV=production npm run babel && npm run sass && npm run tsd",
92 | "start": "node server.js",
93 | "babel": "babel ./src --out-dir ./lib",
94 | "sass": "cpx \"./src/**/*.scss\" ./lib",
95 | "tsd": "cpx \"./src/**/*.d.ts\" ./lib"
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/screenshots/rta.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MaximKomlev/react-toolbox-additions/0e68b68de8a3bd2fc8e976665f6d87ad8a276255/screenshots/rta.gif
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var WebpackDevServer = require('webpack-dev-server');
3 | var config = require('./webpack.config');
4 |
5 | config.entry.push('webpack-dev-server/client?http://localhost:8000');
6 |
7 | new WebpackDevServer(webpack(config), {
8 | contentBase: config.output.path
9 | }).listen(8000, '', function (err, result) {
10 | if (err) {
11 | return console.log(err);
12 | }
13 |
14 | console.log('Listening at http://localhost:8000/');
15 | });
--------------------------------------------------------------------------------
/src/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/commons";
2 |
3 | $indent: $unit *.5 !default;
4 | $button-margin: 0 $indent 0 0 !default;
5 |
6 | @mixin space-between {
7 | margin-right: $indent;
8 | }
9 |
--------------------------------------------------------------------------------
/src/accordion/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/button/theme";
2 | @import "../config";
3 |
4 | $chord-content-padding: 1 * $unit !default;
5 | $chord-label-disabled-opacity: .2 !default;
6 | $chord-label-v-padding: 0.2 * $unit !default;
7 | $chord-label-height: 4.8 * $unit !default;
8 | $chord-icon-height: 2.4 * $unit !default;
9 | $chord-text-height: 1.4 * $unit !default;
10 | $chord-pointer-color: $color-primary !default;
11 | $chord-text: $color-black !default;
12 | $chord-text-color: $chord-text !default;
13 | $chord-text-inactive-color: rgba($chord-text, .7) !default;
14 |
--------------------------------------------------------------------------------
/src/accordion/accordion.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import classnames from 'classnames';
3 | import { themr } from 'react-css-themr';
4 | import { ACCORDION } from '../identifiers.js';
5 | import InjectChord from './chord.js';
6 |
7 | const factory = (Chord) => {
8 | class Accordion extends Component {
9 |
10 | static propTypes = {
11 | children: PropTypes.node,
12 | className: PropTypes.string,
13 | disableAnimation: PropTypes.bool,
14 | index: PropTypes.number,
15 | onChange: PropTypes.func,
16 | theme: PropTypes.shape({
17 | accordion: PropTypes.string
18 | })
19 | };
20 |
21 | static defaultProps = {
22 | index: 0,
23 | disableAnimation: false
24 | };
25 |
26 | //events handler
27 | handleHeaderClick (event, idx, item) {
28 | idx = parseInt(idx);
29 | if (this.props.onChange) {
30 | this.props.onChange(idx);
31 | }
32 | if (item.props.onClick) {
33 | item.props.onClick(event);
34 | }
35 | };
36 |
37 | //private methods
38 | renderChords () {
39 | const chords = [];
40 | let idx = 0;
41 |
42 | React.Children.forEach(this.props.children, (item) => {
43 | if (item.type === Chord) {
44 | if (item.props.children) {
45 | chords.push(React.cloneElement(item, {
46 | id: idx,
47 | key: idx,
48 | theme: this.props.theme,
49 | active: this.props.index === idx,
50 | onClick: this.handleHeaderClick.bind(this, event, idx, item)
51 | }));
52 | ++idx;
53 | }
54 | }
55 | });
56 |
57 | return chords;
58 | }
59 |
60 | render () {
61 | const { className, disableAnimation, theme} = this.props;
62 | const classNames = classnames(theme.accordion, className, {
63 | [theme.disableAnimation]: disableAnimation
64 | });
65 |
66 | return (
67 |
68 |
69 | {this.renderChords()}
70 |
71 |
72 | );
73 | }
74 | }
75 |
76 | return Accordion;
77 | };
78 |
79 | const Accordion = factory(InjectChord);
80 | export default themr(ACCORDION)(Accordion);
81 | export { factory as accordionFactory };
82 | export { Accordion };
83 |
--------------------------------------------------------------------------------
/src/accordion/chord.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import ReactDOM from 'react-dom';
3 | import classnames from 'classnames';
4 | import { FontIcon } from 'react-toolbox/lib/font_icon';
5 | import { themr } from 'react-css-themr';
6 | import { CHORD } from '../identifiers.js';
7 |
8 | const contentId = 'contentId';
9 |
10 | class Chord extends Component {
11 |
12 | constructor(props) {
13 | super();
14 |
15 | this.state.active = props.active;
16 | }
17 |
18 | static propTypes = {
19 | active: PropTypes.bool,
20 | activeClassName: PropTypes.string,
21 | className: PropTypes.string,
22 | disabled: PropTypes.bool,
23 | hidden: PropTypes.bool,
24 | label: PropTypes.node,
25 | labelIcon: PropTypes.node,
26 | labelPostIcon: PropTypes.node,
27 | onActive: PropTypes.func,
28 | onClick: PropTypes.func,
29 | theme: PropTypes.shape({
30 | active: PropTypes.string,
31 | disabled: PropTypes.string,
32 | hidden: PropTypes.string,
33 | label: PropTypes.string,
34 | content: PropTypes.string
35 | })
36 | };
37 |
38 | static defaultProps = {
39 | active: false,
40 | className: '',
41 | disabled: false,
42 | hidden: false
43 | };
44 |
45 | state = {
46 | active: false
47 | };
48 |
49 | //private methods
50 | transitionEndEventName () {
51 | let i,
52 | undefined,
53 | el = document.createElement('div'),
54 | transitions = {
55 | 'transition':'transitionend',
56 | 'OTransition':'otransitionend',
57 | 'MozTransition':'transitionend',
58 | 'WebkitTransition':'webkitTransitionEnd'
59 | };
60 |
61 | for (i in transitions) {
62 | if (transitions.hasOwnProperty(i) && el.style[i] !== undefined) {
63 | return transitions[i];
64 | }
65 | }
66 | }
67 |
68 | collapse() {
69 | let contentEl = ReactDOM.findDOMNode(this.refs[contentId]);
70 | if (contentEl) {
71 | contentEl.style.height = getComputedStyle(contentEl).height;
72 | contentEl.offsetHeight;
73 | contentEl.style.height = 0;
74 | }
75 | }
76 |
77 | expand() {
78 | let contentEl = ReactDOM.findDOMNode(this.refs[contentId]);
79 | if (contentEl) {
80 | let initialHeight = getComputedStyle(contentEl).height;
81 | contentEl.style.height = 'auto';
82 | let newHeight = getComputedStyle(contentEl).height;
83 | contentEl.style.height = initialHeight;
84 | contentEl.offsetHeight;
85 | contentEl.style.height = newHeight;
86 |
87 | let self = this;
88 | contentEl.addEventListener(this.transitionEndEventName(), function transitionEnd(event) {
89 | if (self.state.active) {
90 | contentEl.style.height = 'auto';
91 | }
92 | contentEl.removeEventListener(self.transitionEndEventName(), transitionEnd, false);
93 | }, false)
94 | }
95 | }
96 |
97 | componentDidMount() {
98 | window.addEventListener('resize', this.handleResize);
99 | if (this.props.active) {
100 | this.expand();
101 | } else {
102 | this.collapse();
103 | }
104 | }
105 |
106 | componentDidUpdate (prevProps) {
107 | if (!prevProps.active && this.props.active && this.props.onActive) {
108 | this.props.onActive();
109 | }
110 | }
111 |
112 | componentWillReceiveProps (nextProps) {
113 | this.state.active = nextProps.active;
114 | if (this.state.active) {
115 | this.expand();
116 | } else {
117 | this.collapse();
118 | }
119 | }
120 |
121 | componentWillUnmount () {
122 | window.removeEventListener('resize', this.handleResize);
123 | }
124 |
125 | //events handler
126 | handleClick = (event) => {
127 | if (!this.props.disabled && this.props.onClick) {
128 | this.props.onClick(event);
129 | }
130 | };
131 |
132 | handleResize = () => {
133 | if (this.state.active) {
134 | this.expand();
135 | } else {
136 | this.collapse();
137 | }
138 | };
139 |
140 | render () {
141 | const {
142 | children, id, key,
143 | active, activeClassName, className, disabled, hidden,
144 | label, labelIcon, labelPostIcon, theme
145 | } = this.props;
146 | const _className = classnames(theme.label, {
147 | [theme.withText]: label,
148 | [theme.withIcon]: labelIcon,
149 | [theme.withPostIcon]: labelPostIcon
150 | });
151 |
152 | let lIcon = labelIcon;
153 | if (lIcon && Object.prototype.toString.call(lIcon) !== '[object String]') {
154 | lIcon = React.cloneElement(labelIcon, {
155 | className: classnames(labelIcon.props.className, theme.icon)
156 | });
157 | } else if (labelIcon) {
158 | lIcon =
159 | }
160 |
161 | let lpIcon = labelPostIcon;
162 | if (lpIcon && Object.prototype.toString.call(lpIcon) !== '[object String]') {
163 | lpIcon = React.cloneElement(labelPostIcon, {
164 | className: classnames(labelPostIcon.props.className, theme.postIcon)
165 | });
166 | } else if (labelPostIcon) {
167 | lpIcon =
168 | }
169 |
170 | return (
171 |
172 |
173 | {lIcon}
174 | {label}
175 | {lpIcon}
176 |
177 |
178 | {children}
179 |
180 |
181 | );
182 | }
183 | }
184 |
185 | export default themr(CHORD)(Chord);
186 | export { Chord };
187 |
--------------------------------------------------------------------------------
/src/accordion/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ReactToolbox from "../index";
3 |
4 | export interface AccordionTheme {
5 | /**
6 | * Used for the root element.
7 | */
8 | accordion?: string;
9 | }
10 |
11 | interface AccordionProps extends ReactToolbox.Props {
12 | /**
13 | * The class(s) will be applied to the root elemt.
14 | */
15 | className
16 | /**
17 | * Children to pass through the component.
18 | */
19 | children?: React.ReactNode;
20 | /**
21 | * Disable the animation on children expanding/collapsing.
22 | * @default false
23 | */
24 | disableAnimation?: boolean;
25 | /**
26 | * Expanded element
27 | * @default 0
28 | */
29 | index?: number;
30 | /**
31 | * Callback function that is fired when the Chord changes.
32 | */
33 | onChange?: Function;
34 | /**
35 | * Classnames object defining the component style.
36 | */
37 | theme?: AccordionTheme;
38 | }
39 |
40 | export class Accordion extends React.Component { }
41 |
42 | export interface ChordTheme {
43 | /**
44 | * Added to the chord element (label and content) in case it's active.
45 | */
46 | active?: string;
47 | /**
48 | * Added to the chord element in case it's disabled.
49 | */
50 | disabled?: string;
51 | /**
52 | * Added to the chord element in case it's hidden.
53 | */
54 | hidden?: string;
55 | /**
56 | * Base style of header of chord element.
57 | */
58 | label?: string;
59 | /**
60 | * Base style of content of chord element.
61 | */
62 | content?: string;
63 | }
64 |
65 | interface ChordProps extends ReactToolbox.Props {
66 | /**
67 | * If true, the current component is visible.
68 | */
69 | active?: boolean;
70 | /**
71 | * Additional class name to provide custom styling for the active Chord.
72 | */
73 | activeClassName?: string;
74 | /**
75 | * If true, the current component is not clickable.
76 | * @default false
77 | */
78 | disabled?: boolean;
79 | /**
80 | * If true, the current component is not visible.
81 | * @default false
82 | */
83 | hidden?: boolean;
84 | /**
85 | * Label text for the chord header. Required.
86 | */
87 | label: string;
88 | /**
89 | * Icon for chord header. Required.
90 | */
91 | labelIcon: string;
92 | /**
93 | * Icon behind of the label for chord header.
94 | */
95 | labelPostIcon: string;
96 | /**
97 | * Callback function that is fired when the Chord is activated.
98 | */
99 | onActive?: Function;
100 | /**
101 | * Callback function that is fired when the chord label is clicked.
102 | */
103 | onClick?: Function;
104 | /**
105 | * Classnames object defining the component style.
106 | */
107 | theme?: ChordTheme;
108 | }
109 |
110 | export class Chord extends React.Component { }
111 |
--------------------------------------------------------------------------------
/src/accordion/index.js:
--------------------------------------------------------------------------------
1 | import { themr } from 'react-css-themr';
2 | import { ACCORDION } from '../identifiers.js';
3 | import { accordionFactory } from './accordion.js';
4 | import { Chord } from './chord.js';
5 | import theme from './theme.scss';
6 |
7 | const applyTheme = (Component) => themr(ACCORDION, theme)(Component);
8 | const ThemedChord = applyTheme(Chord);
9 | const ThemedAccordion = applyTheme(accordionFactory(ThemedChord));
10 |
11 | export { ThemedChord as Chord };
12 | export { ThemedAccordion as Accordion };
13 |
--------------------------------------------------------------------------------
/src/accordion/readme.md:
--------------------------------------------------------------------------------
1 | # Accordion
2 |
3 | Provides functionality of Accordion control, actually the component is not defined at(https://www.google.com/design/spec/components),
4 | but designed by using standard components from material design utilizing react-toolbox components library (http://react-toolbox.com/).
5 | It is easy to use and configure, also it is highly customizable.
6 |
7 |
8 | ```jsx
9 | import React, { PropTypes } from 'react';
10 | import FontIcon from 'react-toolbox/lib/font_icon';
11 | import Input from 'react-toolbox/lib/input';
12 | import {Button} from 'react-toolbox/lib/button';
13 | import { ListCheckbox, ListSubHeader, List, ListItem, ListDivider, ListItemText, ListItemContent } from 'react-toolbox/lib/list';
14 |
15 | import {Accordion, Chord} from '../../lib/accordion';
16 | import style from '../style';
17 |
18 | class AccordionTest extends React.Component {
19 |
20 | static propTypes = {
21 | };
22 |
23 | static defaultProps = {
24 | }
25 |
26 | state = {
27 | index: 0
28 | }
29 |
30 | onChange = (idx) => {
31 | this.setState({
32 | index: idx
33 | });
34 | }
35 |
36 | onActive1 = () => {
37 | console.info('Selected chord: ' + this.state.index);
38 | }
39 |
40 | onActive2 = () => {
41 | console.info('Selected chord: ' + this.state.index);
42 | }
43 |
44 | onActive3 = () => {
45 | console.info('Selected chord: ' + this.state.index);
46 | }
47 |
48 | render () {
49 |
50 | return (
51 |
52 | Accordion
53 | Accordion component.
54 |
55 |
56 |
61 |
65 |
66 | The project provides additions for react-toolbox which are not defined at material design and therefore were not included to original react-toolbox components library but it could be useful to have.
67 |
68 |
69 | }
71 | label='Number Two'
72 | onActive={this.onActive2}
73 | >
74 |
75 |
80 |
81 |
84 |
85 |
86 |
87 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | );
106 | }
107 | }
108 | ```
109 |
110 | If you want to provide a theme via context, the component key is `ERTAccordion`.
111 |
112 | ## Accordion
113 |
114 | This component is a wrapper and the main controller of the content that is being displayed as his children.
115 |
116 | ### Properties
117 |
118 | | Name | Type | Default | Description|
119 | |:-----|:-----|:-----|:-----|
120 | | `className` | `String` | `''` | Additional class name to provide custom styling.|
121 | | `disableAnimation` | `Boolean` | `false` | Disable the animation on children expanding/collapsing.|
122 | | `index` | `Number` | `0` | Expanded child |
123 | | `children` | `Elements` | [] | Collection of children .|
124 | | `onChange` | `Function` | | Callback function that is fired when the chord changes.|
125 |
126 | ### Theming
127 |
128 | | Name | Description|
129 | |:---------|:-----------|
130 | | `accordion` | Used for the root element.|
131 |
132 | ## Chord
133 |
134 | Represent a single child element with some properties to describe the chors itself and get children elements as content.
135 |
136 | ### Properties
137 |
138 | | Name | Type | Default | Description|
139 | |:-----|:-----|:-----|:-----|
140 | | `active` | `Boolean` | `false` | If true, the current component is expanded.|
141 | | `activeClassName` | `String` | `''` | Additional class name to provide custom styling for the expanded chord.|
142 | | `className` | `String` | `''` | Additional class name to provide custom styling for each chord.|
143 | | `disabled` | `Boolean` | `false` | If true, the current chord component is not clickable.|
144 | | `hidden` | `Boolean` | `false` | If true, the current chord component is not visible.|
145 | | `label` | `String` | | Label text for the chord header. |
146 | | `labelIcon` | `String` | | Icon for chord header. |
147 | | `labelPostIcon` | `String` | | Icon behind of the label for chord header. |
148 | | `onActive` | `Function` | | Callback function that is fired when the chord is expanded. |
149 | | `onClick` | `Function` | | Callback function that is fired when the chord label is clicked. |
150 |
151 | It is required to provide either a label or an icon (or both).
152 |
153 | ### Theme
154 |
155 | | Name | Description|
156 | |:---------|:-----------|
157 | | `active` | Added to the chord element (label and content) in case it's active.|
158 | | `disabled` | Added to the chord element in case it's disabled.|
159 | | `hidden` | Added to the chord element in case it's hidden.|
160 | | `label` | Base style of header of chord element.|
161 | | `content` | Base style of content of chord element.|
162 |
--------------------------------------------------------------------------------
/src/accordion/theme.scss:
--------------------------------------------------------------------------------
1 | @import "./config";
2 |
3 | .accordion {
4 | position: relative;
5 | height: 100%;
6 | width: 100%;
7 | display: block;
8 |
9 | &.disableAnimation {
10 | .chord {
11 | .content {
12 | transition: none !important;
13 | }
14 | }
15 | }
16 |
17 | .chord {
18 | position: relative;
19 | width: 100%;
20 | display: block;
21 |
22 | &.hidden {
23 | display: none !important;
24 | }
25 |
26 | &.disabled {
27 | opacity: $chord-label-disabled-opacity;
28 | .label {
29 | cursor: default;
30 | }
31 | }
32 |
33 | .content {
34 | position: relative;
35 | height: 0;
36 | box-sizing: border-box;
37 | overflow: hidden;
38 | opacity: 0;
39 | transition: height $animation-duration ease-in-out, opacity $animation-duration linear;
40 | }
41 |
42 | &.active {
43 | margin-bottom: 2 * $chord-content-padding;
44 |
45 | .content {
46 | opacity: 1;
47 | height: auto;
48 | transition: height $animation-duration ease-in-out, opacity $animation-duration linear;
49 | }
50 |
51 | .label {
52 | color: $chord-pointer-color;
53 | margin-bottom: $chord-content-padding;
54 | }
55 | }
56 |
57 | .label {
58 | display: block;
59 | width: 100%;
60 | font-size: $chord-text-height;
61 | font-weight: $font-weight-semi-bold;
62 | padding-top: $chord-label-v-padding;
63 | padding-bottom: $chord-label-v-padding;
64 | margin-bottom: 0;
65 | color: $chord-text-color;
66 | text-transform: uppercase;
67 | transition-timing-function: $animation-curve-default;
68 | transition-duration: $animation-duration;
69 | transition-property: box-shadow, color;
70 | cursor: pointer;
71 |
72 | .text {
73 | position: relative;
74 | display: inline-block;
75 | height: $chord-icon-height;
76 | line-height: $chord-icon-height;
77 | vertical-align: top;
78 | margin-right: $chord-content-padding;
79 | }
80 |
81 | .icon,
82 | .postIcon {
83 | position: relative;
84 | display: inline-block;
85 | height: $chord-icon-height;
86 | width: $chord-icon-height;
87 | line-height: $chord-icon-height;
88 | }
89 |
90 | &.withIcon {
91 | }
92 |
93 | &.withPostButton {
94 | }
95 |
96 | &.withText {
97 | .icon {
98 | margin-right: $chord-content-padding;
99 | }
100 | }
101 |
102 | .postIcon {
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/src/filepicker/_config.scss:
--------------------------------------------------------------------------------
1 | @import "../config";
2 |
3 | $input-min-width: $unit * 4 !default;
4 |
--------------------------------------------------------------------------------
/src/filepicker/filepicker.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import classnames from 'classnames';
3 | import { themr } from 'react-css-themr';
4 |
5 | import {BrowseButton as InjectButton} from 'react-toolbox/lib/button';
6 | import InjectInput from 'react-toolbox/lib/input';
7 | import { FILEPICKER } from '../identifiers.js';
8 |
9 | const factory = (Input, Button) => {
10 | class FilePicker extends Component {
11 |
12 | constructor(props) {
13 | super(props);
14 | this.state = {value: props.value};
15 | }
16 |
17 | static propTypes = {
18 | buttonProperties: React.PropTypes.object,
19 | className: PropTypes.string,
20 | inline: PropTypes.bool,
21 | inputProperties: React.PropTypes.object,
22 | onChange: PropTypes.func,
23 | theme: PropTypes.shape({
24 | button: PropTypes.string,
25 | filepicker: PropTypes.string,
26 | inline: PropTypes.string,
27 | input: PropTypes.string
28 | }),
29 | value: PropTypes.string
30 | };
31 |
32 | static defaultProps = {
33 | buttonProperties: {label: 'BROWSE'},
34 | className: '',
35 | inline: false,
36 | inputProperties: {label: 'SELECT FILE'},
37 | value: undefined
38 | }
39 |
40 | state = {
41 | value: this.props.value
42 | }
43 |
44 | componentWillReceiveProps (nextProps) {
45 | if (this.state.value !== nextProps.value) {
46 | this.setState({
47 | value: nextProps.value
48 | });
49 | }
50 | }
51 |
52 | handlerBrowse = (e) => {
53 | let files = e.target.files;
54 |
55 | if (files && files.length) {
56 | if (this.state.value !== files[0].name) {
57 | if (this.props.onChange) {
58 | this.props.onChange(files[0], files[0].name);
59 | }
60 | }
61 |
62 | this.setState({
63 | value: files[0].name
64 | });
65 | }
66 | }
67 |
68 | render() {
69 | const { className, buttonProperties, inputProperties, value, inline, theme } = this.props;
70 | const css = inline ? 'inline' : null;
71 |
72 | return (
73 |
74 |
79 |
84 |
85 | );}
86 | }
87 | return FilePicker;
88 | };
89 |
90 | const FilePicker = factory(InjectInput, InjectButton);
91 |
92 | export default themr(FILEPICKER)(FilePicker);
93 | export {
94 | factory as filePickerFactory
95 | };
96 | export { FilePicker };
97 |
--------------------------------------------------------------------------------
/src/filepicker/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ReactToolbox from "react-toolbox/lib/index";
3 |
4 | export interface FilePickerTheme {
5 | /**
6 | * Used for the root element.
7 | */
8 | filepicker?: string;
9 | /**
10 | * Used for the input component.
11 | */
12 | input?: string;
13 | /**
14 | * Used for inline style of component.
15 | */
16 | inline?: string;
17 | /**
18 | * Used for the button component.
19 | */
20 | button?: string;
21 | }
22 |
23 | interface FilePickerProps extends ReactToolbox.Props {
24 | /**
25 | * This class will be applied to the root elemt.
26 | */
27 | className?: string;
28 | /**
29 | * This is button base properties like: accent, disabled, icon, ...
30 | */
31 | buttonProperties?: object
32 | /**
33 | * This is input base properties like: hint, disabled, icon, ...
34 | */
35 | inputProperties?: object
36 | /**
37 | * If true, the component will apear inline.
38 | * @default false
39 | */
40 | inline?: boolean
41 | /**
42 | * Callback called when the input is changing.
43 | */
44 | onChange?: Function;
45 | /**
46 | * Classnames object defining the component style.
47 | */
48 | theme?: FilePickerTheme;
49 | /**
50 | * This is initial value of input component.
51 | */
52 | value?: string
53 | }
54 |
55 | export class FilePicker extends React.Component { }
56 |
57 | export default FilePicker;
58 |
--------------------------------------------------------------------------------
/src/filepicker/index.js:
--------------------------------------------------------------------------------
1 | import { themr } from 'react-css-themr';
2 | import { FILEPICKER } from '../identifiers.js';
3 | import { filePickerFactory } from './filepicker.js';
4 | import { BrowseButton } from 'react-toolbox/lib/button';
5 | import { Input } from 'react-toolbox/lib/input';
6 | import theme from './theme.scss';
7 |
8 | const FilePicker = filePickerFactory(Input, BrowseButton);
9 |
10 | const ThemedFilePicker = themr(FILEPICKER, theme)(FilePicker);
11 | export default ThemedFilePicker;
12 | export { ThemedFilePicker as FilePicker };
13 |
--------------------------------------------------------------------------------
/src/filepicker/readme.md:
--------------------------------------------------------------------------------
1 | # FilePicker
2 |
3 | Provides functionality of filepicker control, actually the component is not defined at(https://www.google.com/design/spec/components),
4 | but designed by using standard components from material design utilizing react-toolbox components library (http://react-toolbox.com/).
5 | It is easy to use and configure, also it is highly customizable.
6 |
7 |
8 | ```jsx
9 | import FilePicker from 'react-toolbox-additions/lib/filepicker';
10 |
11 | const FilePickerTest = () => {
12 |
13 | onChange (fobj, fname) {
14 | console.info('Selected file : ' + fname);
15 | }
16 |
17 | return (
18 |
23 | );
24 | };
25 | ```
26 |
27 | If you want to provide a theme via context, the component key is `ERTFilePicker`.
28 |
29 | ## Properties
30 |
31 | | Name | Type | Default | Description|
32 | |:-----|:-----|:-----|:-----|
33 | | `className` | `String` | `` | This class will be applied to the root elemt.|
34 | | `buttonProperties` | `String` | {label: 'BROWSE'} | This is button base properties like: accent, disabled, icon, ...|
35 | | `inputProperties` | `String` | {label: 'SELECT FILE'} | This is input base properties like: hint, disabled, icon, ...|
36 | | `inline` | `boolean` | false | If true, the component will apear inline.|
37 | | `onChange` | `Function` | | Callback called when the input is changing.|
38 | | `theme` | `String` | | Classnames object defining the component style.|
39 | | `value` | `String` | `` | This is initial value of input component.|
40 |
41 |
42 | ## Theme
43 |
44 | | Name | Description|
45 | |:---------|:-----------|
46 | | `filepicker` | Used for the root element.|
47 | | `input` | Used for the input element.|
48 | | `inline` | Used for inline style of component.|
49 | | `button` | Used for the button element.|
50 |
--------------------------------------------------------------------------------
/src/filepicker/theme.scss:
--------------------------------------------------------------------------------
1 | @import "./config";
2 |
3 | .filepicker {
4 |
5 | > * {
6 | display: inline-block;
7 | vertical-align: middle;
8 | }
9 |
10 | &.inline {
11 | display: inline-block;
12 | vertical-align: middle;
13 | }
14 |
15 | .input {
16 | @include space-between;
17 | min-width: $input-min-width;
18 |
19 | & span:last-child {
20 | opacity: 1 !important;
21 | }
22 | }
23 |
24 | /*ie fix*/
25 | .iefix {
26 | input {
27 | top: 0 !important;
28 | left: 0 !important;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/identifiers.js:
--------------------------------------------------------------------------------
1 | export const ACCORDION = 'ERTAccordion';
2 | export const CHORD = 'ERTChord';
3 | export const PAGER = 'ERTPager';
4 | export const FILEPICKER = 'ERTFilePicker';
5 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | export Pager from './pager';
2 | export FilePicker from './filepicker';
3 | export * from './accordion';
4 |
--------------------------------------------------------------------------------
/src/pager/_config.scss:
--------------------------------------------------------------------------------
1 | @import "~react-toolbox/lib/button/theme";
2 | @import "../config";
3 |
--------------------------------------------------------------------------------
/src/pager/index.d.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import ReactToolbox from "react-toolbox/lib/index";
3 |
4 | export interface PagerTheme {
5 | /**
6 | * Used for the root element.
7 | */
8 | pager?: string;
9 | /**
10 | * Used for the active page.
11 | */
12 | active?: string;
13 | /**
14 | * Used for the first and last page buttons.
15 | */
16 | firstLastPagesButton?: string;
17 | /**
18 | * Used for the next and previous arrow buttons.
19 | */
20 | leftRightArrowButton?: string;
21 | /**
22 | * Used for the next and previous range pages buttons.
23 | */
24 | leftRightRangeButton?: string;
25 | /**
26 | * Used for the regular page buttons.
27 | */
28 | pagesButton?: string;
29 | }
30 |
31 | interface PagerProps extends ReactToolbox.Props {
32 | /**
33 | * Used for the previous button content.
34 | */
35 | prevButtonLabel?: string;
36 | /**
37 | * Used for the left range button content
38 | */
39 | rangeLeftButtonLabel?: string;
40 | /**
41 | * Used for the right range button content
42 | */
43 | rangeRightButtonLabel?: string;
44 | /**
45 | * Used for the next button content
46 | */
47 | nextButtonLabel?: string;
48 | /**
49 | * A Number with the currently selected page
50 | */
51 | currentPage?: number;
52 | /**
53 | * A Number of total pages.
54 | */
55 | totalPages?: number;
56 | /**
57 | * A Number of pages visible in control except next, previous and ranges buttons, the minimum value is 2.
58 | */
59 | visiblePagesBlockSize?: number;
60 | /**
61 | * Callback called when the page is changing.
62 | */
63 | onPageChange?: Function;
64 | /**
65 | * Classnames object defining the component style.
66 | */
67 | theme?: PagerTheme;
68 | /**
69 | * This class will be applied to the root elemt.
70 | */
71 | pagerClassName?: string;
72 | /**
73 | * Defining default style of first, last page buttons.
74 | * it can have following styles:
75 | * accent,
76 | * flat,
77 | * inverse,
78 | * mini,
79 | * neutral,
80 | * primary,
81 | * raised,
82 | * toggle
83 | */
84 | firstLastPagesButtonStyles?: object;
85 | /**
86 | * Defining default style of next, previous buttons.
87 | * it can have following styles:
88 | * accent,
89 | * flat,
90 | * inverse,
91 | * mini,
92 | * neutral,
93 | * primary,
94 | * raised,
95 | * toggle
96 | */
97 | leftRightArrowButtonStyles?: object;
98 | /**
99 | * Defining default style of left, right range buttons.
100 | * it can have following styles:
101 | * accent,
102 | * flat,
103 | * inverse,
104 | * mini,
105 | * neutral,
106 | * primary,
107 | * raised,
108 | * toggle
109 | */
110 | leftRightRangeButtonStyles?: object;
111 | /**
112 | * Defining default style of regular page buttons.
113 | * it can have following styles:
114 | * accent,
115 | * flat,
116 | * inverse,
117 | * mini,
118 | * neutral,
119 | * primary,
120 | * raised,
121 | * toggle
122 | */
123 | pagesButtonStyles?: object;
124 | }
125 |
126 | export class Pager extends React.Component { }
127 |
128 | export default Pager;
129 |
--------------------------------------------------------------------------------
/src/pager/index.js:
--------------------------------------------------------------------------------
1 | import { themr } from 'react-css-themr';
2 | import { PAGER } from '../identifiers.js';
3 | import { pagerFactory } from './pager.js';
4 | import Page from './page.js';
5 | import theme from './theme.scss';
6 |
7 | const Pager = pagerFactory(Page);
8 |
9 | const ThemedPager = themr(PAGER, theme)(Pager);
10 | export default ThemedPager;
11 | export { ThemedPager as Pager };
12 |
--------------------------------------------------------------------------------
/src/pager/page.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import classnames from 'classnames';
3 |
4 | import Button from 'react-toolbox/lib/button';
5 |
6 | export const BUTTON_TYPE = {
7 | PAGE: 0,
8 | RANGE: 1,
9 | ARROW: 2
10 | }
11 |
12 | class Page extends Component {
13 |
14 | constructor(props) {
15 | super();
16 |
17 | this.state.data = props.data;
18 | this.state.buttonType = props.buttonType;
19 | this.state.label = props.children;
20 | }
21 |
22 | static propTypes = {
23 | activeClassName: PropTypes.string,
24 | buttonClassNames: PropTypes.object,
25 | buttonStyles: PropTypes.object,
26 | buttonType: PropTypes.oneOf([BUTTON_TYPE.PAGE, BUTTON_TYPE.RANGE, BUTTON_TYPE.ARROW]),
27 | onPageClick: PropTypes.func
28 | }
29 |
30 | static defaultProps = {
31 | buttonType: 0,
32 | buttonStyles: {0: {flat: true}},
33 | buttonClassNames: {0: null}
34 | }
35 |
36 | state = {
37 | disabled: false,
38 | active: false,
39 | data: 0,
40 | buttonType: 0,
41 | label: null
42 | }
43 |
44 | componentWillReceiveProps (nextProps) {
45 | if (nextProps.children && !isNaN(nextProps.children)
46 | && this.state.label !== nextProps.children) {
47 | this.setState({
48 | label: nextProps.children
49 | });
50 | }
51 | if (nextProps.buttonType && !isNaN(nextProps.buttonType)
52 | && this.state.buttonType !== nextProps.buttonType) {
53 | this.setState({
54 | buttonType: nextProps.buttonType
55 | });
56 | }
57 | }
58 |
59 | //events handlers
60 | handlerClick() {
61 | if (this.props.onPageClick){
62 | this.props.onPageClick(this.state.data, this.state.buttonType);
63 | }
64 | }
65 |
66 | //rendering
67 | render () {
68 | let styles = this.props.buttonStyles[this.state.buttonType];
69 | let className = this.props.buttonClassNames[this.state.buttonType];
70 |
71 | if (styles['disabled'] === undefined) {
72 | styles = {...styles, disabled: this.state.disabled}
73 | } else {
74 | styles['disabled'] = this.state.disabled;
75 | }
76 |
77 | return (
78 |
82 | { this.state.label }
83 |
84 | );
85 | }
86 |
87 | //public methods
88 | update(active, data, label, type) {
89 | this.setState({
90 | active: active,
91 | data: data,
92 | buttonType: type,
93 | label: label
94 | });
95 | }
96 |
97 | disable(v) {
98 | this.setState({
99 | disabled: v
100 | });
101 | }
102 | }
103 |
104 | export default Page;
--------------------------------------------------------------------------------
/src/pager/pager.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import classnames from 'classnames';
3 | import { themr } from 'react-css-themr';
4 |
5 | import InjectPage, {BUTTON_TYPE} from './page.js';
6 | import { PAGER } from '../identifiers.js';
7 |
8 | const isOnePage = (first, last) => {
9 | return first === last || !last;
10 | };
11 |
12 | const isBorderPage = (curr, border) => {
13 | return curr === border;
14 | };
15 |
16 | const clone = (src) => {
17 | return JSON.parse(JSON.stringify(src));
18 | }
19 |
20 | const prevPageId = 'prev';
21 | const nextPageId = 'next';
22 |
23 | const initialVisiblePagesBlockSize = 3;
24 | const initialCurrentPage = 1;
25 | const first = 1;
26 | /*
27 | * adjustment of start and end elements at range to have equal elements during navigation
28 | * 2 - because we already have the rendered first and last button
29 | */
30 | const adjustment = 2;
31 |
32 | const factory = (Page) => {
33 | class Pager extends Component {
34 |
35 | constructor(props) {
36 | super();
37 |
38 | if (props) {
39 | this.state.currentPage = props.currentPage;
40 | this.state.totalPages = props.totalPages;
41 | }
42 | }
43 |
44 | static propTypes = {
45 | currentPage: PropTypes.oneOfType([
46 | PropTypes.string,
47 | PropTypes.number
48 | ]).isRequired,
49 | firstLastPagesButtonStyles: PropTypes.object,
50 | leftRightArrowButtonStyles: PropTypes.object,
51 | leftRightRangeButtonStyles: PropTypes.object,
52 | nextButtonLabel: PropTypes.oneOfType([
53 | PropTypes.string,
54 | PropTypes.element
55 | ]),
56 | onPageChange: PropTypes.func,
57 | pagerClassName: PropTypes.string,
58 | pagesButtonStyles: PropTypes.object,
59 | prevButtonLabel: PropTypes.oneOfType([
60 | PropTypes.string,
61 | PropTypes.element
62 | ]),
63 | rangeLeftButtonLabel: PropTypes.oneOfType([
64 | PropTypes.string,
65 | PropTypes.element
66 | ]),
67 | rangeRightButtonLabel: PropTypes.oneOfType([
68 | PropTypes.string,
69 | PropTypes.element
70 | ]),
71 | theme: PropTypes.shape({
72 | pager: PropTypes.string,
73 | active: PropTypes.string,
74 | firstLastPagesButton: PropTypes.string,
75 | leftRightArrowButton: PropTypes.string,
76 | leftRightRangeButton: PropTypes.string,
77 | pagesButton: PropTypes.string
78 | }),
79 | totalPages: PropTypes.oneOfType([
80 | PropTypes.string,
81 | PropTypes.number
82 | ]).isRequired,
83 | visiblePagesBlockSize: PropTypes.oneOfType([
84 | PropTypes.string,
85 | PropTypes.number
86 | ]).isRequired
87 | }
88 |
89 | static defaultProps = {
90 | currentPage: initialCurrentPage,
91 | totalPages: initialCurrentPage,
92 | firstLastPagesButtonStyles: {flat: true},
93 | leftRightArrowButtonStyles: {raised: true},
94 | leftRightRangeButtonStyles: {flat: true},
95 | nextButtonLabel: '\u003E',
96 | pagesButtonStyles: {flat: true},
97 | prevButtonLabel: '\u003C',
98 | rangeLeftButtonLabel: '...',
99 | rangeRightButtonLabel: '...',
100 | visiblePagesBlockSize: initialVisiblePagesBlockSize
101 | }
102 |
103 | //fields
104 | _ranges = {
105 | leftEnd: null,
106 | rightStart: null
107 | }
108 |
109 | _pages = [];
110 |
111 | state = {
112 | currentPage: initialCurrentPage,
113 | totalPages: initialCurrentPage
114 | }
115 |
116 | componentWillReceiveProps (nextProps) {
117 | if (nextProps.currentPage && !isNaN(Number(nextProps.currentPage))
118 | && this.state.currentPage !== nextProps.currentPage) {
119 | this._pages.splice(0);
120 | this.setState({
121 | currentPage: Number(nextProps.currentPage < first ? first : nextProps.currentPage)
122 | });
123 | }
124 | if (nextProps.totalPages && !isNaN(Number(nextProps.totalPages))
125 | && this.state.totalPages !== nextProps.totalPages) {
126 | this._pages.splice(0);
127 | this.setState({
128 | totalPages: Number(nextProps.totalPages < first ? first : nextProps.totalPages)
129 | });
130 | }
131 | if (nextProps.visiblePagesBlockSize && !isNaN(Number(nextProps.visiblePagesBlockSize))
132 | && this.state.visiblePagesBlockSize !== nextProps.visiblePagesBlockSize) {
133 | this._pages.splice(0);
134 | this.setState({
135 | visiblePagesBlockSize: Number( nextProps.visiblePagesBlockSize < nextProps.totalPages ? nextProps.visiblePagesBlockSize : nextProps.totalPages)
136 | });
137 | }
138 | }
139 |
140 | componentWillUnmount() {
141 | this._pages.splice(0);
142 | }
143 |
144 | componentDidMount() {
145 | this.updateState(this.state.currentPage, this.state.totalPages);
146 | }
147 |
148 | componentDidUpdate() {
149 | this.updatePages(this.state.currentPage, this.state.totalPages);
150 | }
151 |
152 | //events handlers
153 | handlerPageClick (page, type) {
154 | if (type === BUTTON_TYPE.RANGE) {
155 | this.handlerRangeClick(page);
156 | return;
157 | }
158 |
159 | const oldValue = this.state.currentPage;
160 | const newValue = page;
161 |
162 | this.updateState(newValue);
163 |
164 | if (this.props.onPageChange) {
165 | this.props.onPageChange(newValue, oldValue);
166 | }
167 | }
168 |
169 | handlerRangeClick (key) {
170 | const curr = this.state.currentPage;
171 | const last = this.state.totalPages;
172 |
173 | const right = !this._ranges.rightStart ? last : this._ranges.rightStart;
174 | const left = !this._ranges.leftEnd ? first : this._ranges.leftEnd;
175 |
176 | let newValue = curr;
177 | let sum = first + left;
178 | if (key === prevPageId) {
179 | newValue = (sum >> 1); //rounding to left
180 | } else {
181 | sum = last + right;
182 | newValue = (sum >> 1) + (sum % 2); //rounding to right
183 | }
184 |
185 | this.updateState(newValue);
186 |
187 | if (this.props.onPageChange) {
188 | this.props.onPageChange(newValue, curr);
189 | }
190 | }
191 |
192 | handlerPrevNextClick (key, type) {
193 | const oldValue = this.state.currentPage;
194 | const newValue = key === prevPageId ? oldValue - 1 : oldValue + 1;
195 |
196 | this.updateState(newValue);
197 |
198 | if (this.props.onPageChange) {
199 | this.props.onPageChange(newValue, oldValue);
200 | }
201 | }
202 |
203 | //private methods
204 | updateState(newValue) {
205 | this.state.currentPage = newValue;
206 |
207 | if (this._pages.length > 0) {
208 | this.updatePages(newValue, this.state.totalPages);
209 | } else {
210 | this.forceUpdate();
211 | }
212 | }
213 |
214 | updatePages (currPage, totalPages) {
215 | let curr = currPage;
216 | let last = totalPages;
217 |
218 | const blockSize = this.props.visiblePagesBlockSize === 1 ? adjustment : this.props.visiblePagesBlockSize;
219 |
220 | const padding = blockSize >> 1;
221 | const left = curr - padding * (blockSize % 2); //in case of even visiblePagesBlockSize
222 | const right = curr + padding;
223 |
224 | const blocksNumber = Math.ceil(last / blockSize);
225 | let currentBlock = Math.ceil(curr / blockSize);
226 |
227 | let start = ((currentBlock - 1) * blockSize) + first;
228 | let end = start + blockSize - first;
229 |
230 | if (currentBlock === 1) { //adjust set of buttons if current is on the left boundary
231 | end += adjustment;
232 | end = (last - first) === end ? last : end;
233 | } else if (currentBlock < blocksNumber) { //adjustment set of buttons if current is between boundaries
234 | start = left;
235 | end = right;
236 |
237 | currentBlock = Math.ceil((totalPages - end === 1 ? totalPages : end ) / blockSize);
238 | }
239 |
240 | if (currentBlock === blocksNumber) { //adjustment set of buttons if current is on the right boundary
241 | start = last - (blockSize + adjustment - first);
242 | start = start - 1 <= first ? first : start;
243 | end = last;
244 | }
245 |
246 | this.refs[prevPageId].disable(curr === first);
247 |
248 | let buttonIdx = 0;
249 |
250 | if (currentBlock > 1 && (start - 1) > first) {
251 | this.refs[buttonIdx].update(curr === first, first, String(first), BUTTON_TYPE.FLPAGE);
252 | ++buttonIdx;
253 |
254 | this.refs[buttonIdx].update(false, prevPageId, this.props.rangeLeftButtonLabel, BUTTON_TYPE.RANGE);
255 | ++buttonIdx;
256 | }
257 |
258 | for (let i = start; i <= last && i <= end; ++i) {
259 | let bType = BUTTON_TYPE.PAGE;
260 | if (i === first || i === last) {
261 | bType = BUTTON_TYPE.FLPAGE;
262 | }
263 | this.refs[buttonIdx].update(curr === i, i, String(i), bType);
264 | ++buttonIdx;
265 | }
266 |
267 | if (currentBlock < blocksNumber && end < last) {
268 | this.refs[buttonIdx].update(false, nextPageId, this.props.rangeRightButtonLabel, BUTTON_TYPE.RANGE);
269 | ++buttonIdx;
270 |
271 | this.refs[buttonIdx].update(curr === last, last, String(last), BUTTON_TYPE.FLPAGE);
272 | ++buttonIdx;
273 | }
274 |
275 | this.refs[nextPageId].disable(curr === last);
276 |
277 | // keep range boundaries to calculate correct navigation through the range
278 | this._ranges.leftEnd = start;
279 | this._ranges.rightStart = end - 1;
280 | }
281 |
282 | //rendering
283 | renderPages (currPage, totalPages) {
284 | this._pages.splice(0);
285 |
286 | let curr = currPage;
287 | let last = totalPages < first ? first : totalPages;
288 | if (curr < first || curr > last) {
289 | curr = curr < first ? first : curr > last ? last : curr;
290 | this.setState({
291 | currentPage: curr
292 | });
293 | }
294 |
295 | const content = [];
296 |
297 | let buttonsCount = this.props.visiblePagesBlockSize + adjustment + 2;
298 | buttonsCount = buttonsCount > last ? last : buttonsCount;
299 |
300 | let possibleButtonClassNames = {};
301 | possibleButtonClassNames[BUTTON_TYPE.FLPAGE] = classnames(this.props.theme.firstLastPagesButton);
302 | possibleButtonClassNames[BUTTON_TYPE.PAGE] = classnames(this.props.theme.pagesButton);
303 | possibleButtonClassNames[BUTTON_TYPE.RANGE] = classnames(this.props.theme.leftRightRangeButton);
304 | possibleButtonClassNames[BUTTON_TYPE.ARROW] = classnames(this.props.theme.leftRightArrowButton);
305 |
306 | let possibleLeftButtoStyles = {};
307 | possibleLeftButtoStyles[BUTTON_TYPE.ARROW] = clone(this.props.leftRightArrowButtonStyles);
308 | possibleLeftButtoStyles[BUTTON_TYPE.ARROW].disabled = isOnePage(first, this.state.totalPages) || isBorderPage(this.state.currentPage, first);
309 | content.push(
310 |
318 | { this.props.prevButtonLabel }
319 |
320 | );
321 |
322 | let possibleButtoStyles = {};
323 | possibleButtoStyles[BUTTON_TYPE.FLPAGE] = this.props.firstLastPagesButtonStyles;
324 | possibleButtoStyles[BUTTON_TYPE.PAGE] = this.props.pagesButtonStyles;
325 | possibleButtoStyles[BUTTON_TYPE.RANGE] = this.props.leftRightRangeButtonStyles;
326 | for (let i = 0; i < buttonsCount; ++i) {
327 | content.push(
328 |
338 | { String(i) }
339 |
340 | );
341 | this._pages.push(i);
342 | }
343 |
344 | let possibleRightButtoStyles = {};
345 | possibleRightButtoStyles[BUTTON_TYPE.ARROW] = clone(this.props.leftRightArrowButtonStyles);
346 | possibleRightButtoStyles[BUTTON_TYPE.ARROW].disabled = isOnePage(first, this.state.totalPages) || isBorderPage(this.state.currentPage, this.state.totalPages);
347 | content.push(
348 |
356 | { this.props.nextButtonLabel }
357 |
358 | );
359 |
360 | return content;
361 | }
362 |
363 | render () {
364 | return (
365 |
366 | {
367 | this.renderPages(this.state.currentPage, this.state.totalPages)
368 | }
369 |
);
370 | }
371 | }
372 |
373 | return Pager;
374 | };
375 |
376 | const Pager = factory(InjectPage);
377 |
378 | export default themr(PAGER)(Pager);
379 | export {
380 | factory as pagerFactory
381 | };
382 | export { Pager };
383 |
--------------------------------------------------------------------------------
/src/pager/readme.md:
--------------------------------------------------------------------------------
1 | # Pager
2 |
3 | Provides functionality of pagination control, actually the component is not defined at(https://www.google.com/design/spec/components),
4 | but designed by using standard components from material design utilizing react-toolbox components library (http://react-toolbox.com/).
5 | It is easy to use and configure, also it is highly customizable.
6 |
7 |
8 | ```jsx
9 | import Pager from 'react-toolbox-additions/lib/pager';
10 | import FontIcon from 'react-toolbox-additions/lib/font_icon';
11 |
12 | const PagerTest = () => {
13 |
14 | onPageChange = (newPage, oldPage) => {
15 | console.info('Selected page : ' + newPage + ', Previous page: ' + oldPage);
16 | }
17 |
18 | return (
19 | ) }
21 | nextButtonLabel={ ( ) }
22 | rangeLeftButtonLabel={( )}
23 | rangeRightButtonLabel={( )}
24 | totalPages={29}
25 | currentPage={5}
26 | visiblePagesBlockSize={3}
27 | onPageChange={onPageChange}
28 | />
29 | );
30 | };
31 | ```
32 |
33 | If you want to provide a theme via context, the component key is `ERTPager`.
34 |
35 | ## Properties
36 |
37 | | Name | Type | Default | Description|
38 | |:-----|:-----|:-----|:-----|
39 | | `prevButtonLabel` | `String` | `\u003C` | Used for the previous button label content, it can be text or FontIcon element.|
40 | | `nextButtonLabel` | `String` | `\u003E` | Used for the next button label content, it can be text or FontIcon element.|
41 | | `rangeLeftButtonLabel` | `String` | `...` | Used for the left range button label content, it can be text or FontIcon element.|
42 | | `rangeRightButtonLabel` | `String` | `...` | Used for the right range button label content, it can be text or FontIcon element.|
43 | | `currentPage` | `Number` | `1` | A Number with the currently selected page.|
44 | | `totalPages` | `Number` | `1` | A Number of total pages.|
45 | | `visiblePagesBlockSize` | `Number` | `3` | A Number of pages visible in control except next, previous and ranges buttons, the minimum value is 2.|
46 | | `onPageChange` | `Function` | | Callback called when the page is changing.|
47 | | `theme` | `String` | | Classnames object defining the component style.|
48 | | `pagerClassName` | `String` | | This class will be applied to the root elemt.|
49 | | `firstLastPagesButtonStyles` | `Object` | {raised: true} | Defining default style of first and last page buttons.|
50 | | `leftRightArrowButtonStyles` | `Object` | {raised: true} | Defining default style of next and previous arrow buttons.|
51 | | `leftRightRangeButtonStyles` | `Object` | {flat: true} | Defining default style of left and right range buttons.|
52 | | `pagesButtonStyles` | `Object` | {flat: true} | Defining default style of regular pages buttons.|
53 |
54 |
55 | ## Theme
56 |
57 | | Name | Description|
58 | |:---------|:-----------|
59 | | `pager` | Used for the root element.|
60 | | `active` | Used for the active page.|
61 | | `firstLastPagesButton` | Used for the first and last arrow buttons.|
62 | | `leftRightArrowButton` | Used for the next and previous arrow buttons.|
63 | | `leftRightRangeButton` | Used for the next and previous range pages buttons.|
64 | | `pagesButton` | Used for the regular pages buttons.|
--------------------------------------------------------------------------------
/src/pager/theme.scss:
--------------------------------------------------------------------------------
1 | @import "./config";
2 |
3 | .pager {
4 | display: inline-block;
5 | vertical-align: middle;
6 |
7 | .firstLastPagesButton,
8 | .leftRightArrowButton,
9 | .leftRightRangeButton,
10 | .pagesButton {
11 | min-width: $button-height;
12 | margin: $button-margin;
13 | }
14 |
15 | .active {
16 | text-decoration: underline;
17 | }
18 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const pkg = require('./package');
2 | const webpack = require('webpack');
3 | const path = require('path');
4 | const autoprefixer = require('autoprefixer');
5 | var ExtractTextPlugin = require('extract-text-webpack-plugin');
6 | var HtmlWebpackPlugin = require('html-webpack-plugin');
7 |
8 | module.exports = {
9 | context: __dirname,
10 | devtool: 'source-map',
11 | entry: [
12 | 'babel-polyfill',
13 | './example'
14 | ],
15 | output: {
16 | path: path.join(__dirname, 'dist'),
17 | filename: 'bundle.js',
18 | publicPath: './'
19 | },
20 | resolve: {
21 | extensions: ['', '.scss', '.js', '.jsx', '.json'],
22 | modulesDirectories: [
23 | 'node_modules',
24 | path.resolve(__dirname, './node_modules')
25 | ],
26 | packageMains: ['browser', 'web', 'browserify', 'main', 'style']
27 | },
28 | resolveLoader: { fallback: path.join(__dirname, "node_modules") },
29 | module: {
30 | loaders: [
31 | {
32 | test: /\.(js|jsx)$/,
33 | loader: 'babel',
34 | exclude: [/(node_modules)/],
35 | query: {
36 | presets: ['es2015', 'stage-0', 'react']
37 | }
38 | }, {
39 | test: /\.(scss|css)$/,
40 | loader: ExtractTextPlugin.extract('style', 'css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?sourceMap')
41 | }
42 | ]
43 | },
44 | postcss: [autoprefixer],
45 | plugins: [
46 | new ExtractTextPlugin('styles.css', { allChunks: true }),
47 | new webpack.NoErrorsPlugin(),
48 | new webpack.DefinePlugin({
49 | 'process.env.NODE_ENV': JSON.stringify('development'),
50 | VERSION: JSON.stringify(pkg.version)
51 | }),
52 | new HtmlWebpackPlugin({
53 | template: path.join(__dirname, 'example/index.html')
54 | })
55 | ]
56 | };
57 |
--------------------------------------------------------------------------------