├── .gitignore
├── .idea
├── inspectionProfiles
│ └── Project_Default.xml
├── misc.xml
├── modules.xml
├── react-validation.iml
├── vcs.xml
└── workspace.xml
├── README.md
├── config
└── webpack.config.prod.js
├── package.json
├── public
└── index.html
├── src
├── App.js
├── components
│ ├── base
│ │ └── index.js
│ ├── button
│ │ └── index.js
│ ├── form
│ │ └── index.js
│ ├── input
│ │ └── index.js
│ ├── select
│ │ └── index.js
│ └── textarea
│ │ └── index.js
├── hocs
│ ├── button
│ │ └── index.js
│ ├── control
│ │ └── index.js
│ └── form
│ │ └── index.js
├── index.js
└── main.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 | .idea/
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/react-validation.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | <<<<<<< HEAD
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | =======
21 |
22 | >>>>>>> Updated link.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | <<<<<<< HEAD
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | =======
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | >>>>>>> Updated link.
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 | _byComponent
185 | _refs
186 | _byRef
187 | component
188 | props
189 | _isCheckable
190 | _errors
191 | _error
192 | 123
193 | _isChanged
194 | MyInput
195 | MySelect
196 | MyTextarea
197 | _getError
198 | console
199 | isChanged
200 | _updateValue
201 | byId
202 | console.log
203 | _setValue
204 | state.byIdWithProps[id]
205 | byIdWithProps
206 | nextID
207 | without
208 | omit
209 | componentDidMount
210 | Validation.components.
211 | alpha
212 | validations
213 | _setErrors
214 |
215 |
216 | _byComponent
217 | _byRef
218 | _components
219 | error
220 | Input
221 | Select
222 | Textarea
223 | _setProps
224 | byId
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 | <<<<<<< HEAD
260 |
261 |
262 |
263 |
264 | =======
265 |
266 |
267 |
268 |
269 |
270 |
271 | >>>>>>> Updated link.
272 |
273 |
274 |
275 |
276 |
277 |
278 | false
279 |
280 | false
281 | false
282 | true
283 |
284 |
285 | true
286 | DEFINITION_ORDER
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 | <<<<<<< HEAD
323 |
324 |
325 |
326 |
327 |
328 | =======
329 | >>>>>>> Updated link.
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 | 1506498525775
381 |
382 |
383 | 1506498525775
384 |
385 |
386 |
387 |
388 | <<<<<<< HEAD
389 |
390 | =======
391 |
392 |
393 | >>>>>>> Updated link.
394 |
395 |
396 | 1506956934668
397 |
398 |
399 |
400 | 1506956934668
401 |
402 |
403 | 1507128580095
404 |
405 |
406 |
407 | 1507128580095
408 |
409 |
410 | 1507129809617
411 |
412 |
413 |
414 | 1507129809617
415 |
416 |
417 | 1507298361847
418 |
419 |
420 |
421 | 1507298361847
422 |
423 |
424 |
425 |
426 |
427 | <<<<<<< HEAD
428 |
429 | =======
430 |
431 | >>>>>>> Updated link.
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 | <<<<<<< HEAD
440 |
441 |
442 | =======
443 |
444 | >>>>>>> Updated link.
445 |
446 |
447 |
448 | <<<<<<< HEAD
449 |
450 |
451 | =======
452 |
453 | >>>>>>> Updated link.
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 |
500 |
501 |
502 |
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 | <<<<<<< HEAD
515 |
516 |
517 | =======
518 |
519 |
520 | >>>>>>> Updated link.
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 | <<<<<<< HEAD
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 | =======
590 |
591 |
592 | >>>>>>> Updated link.
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 | <<<<<<< HEAD
624 |
625 |
626 | =======
627 |
628 |
629 | >>>>>>> Updated link.
630 |
631 |
632 |
633 |
634 |
635 | <<<<<<< HEAD
636 |
637 |
638 | =======
639 |
640 |
641 | >>>>>>> Updated link.
642 |
643 |
644 |
645 |
646 |
647 | <<<<<<< HEAD
648 |
649 |
650 | =======
651 |
652 |
653 | >>>>>>> Updated link.
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 | <<<<<<< HEAD
664 |
665 |
666 | =======
667 |
668 |
669 | >>>>>>> Updated link.
670 |
671 |
672 |
673 |
674 |
675 | <<<<<<< HEAD
676 |
677 |
678 | =======
679 |
680 |
681 | >>>>>>> Updated link.
682 |
683 |
684 |
685 |
686 |
687 | <<<<<<< HEAD
688 |
689 |
690 | =======
691 |
692 |
693 | >>>>>>> Updated link.
694 |
695 |
696 |
697 |
698 |
699 | <<<<<<< HEAD
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 | =======
726 |
727 |
728 | >>>>>>> Updated link.
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 | <<<<<<< HEAD
738 |
739 |
740 | =======
741 |
742 |
743 | >>>>>>> Updated link.
744 |
745 |
746 |
747 |
748 |
749 | <<<<<<< HEAD
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 | =======
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 | >>>>>>> Updated link.
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 | <<<<<<< HEAD
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 | =======
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 | >>>>>>> Updated link.
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 | <<<<<<< HEAD
874 |
875 |
876 | =======
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 | >>>>>>> Updated link.
888 |
889 |
890 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
902 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
925 |
926 |
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
942 |
943 |
944 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-validation
2 |
3 | [](https://badge.fury.io/js/react-validation) [](https://travis-ci.org/Lesha-spr/react-validation) [](https://coveralls.io/github/Lesha-spr/react-validation?branch=master) [](https://david-dm.org/Lesha-spr/react-validation) [](https://david-dm.org/Lesha-spr/react-validation/?type=dev)
4 |
5 | Component to provide simple form validation for React components. It uses the [Controlled Components](https://facebook.github.io/react/docs/forms.html#controlled-components) approach for validation.
6 |
7 | It is not easy to validate forms with React. The reason is a one-way data flow style. In this case we can't affect forms from the inputs in an easy way.
8 | React-validation provides several components which are 'connected' to the form via the input's method attached by the Form component.
9 |
10 | ### [DEMO](http://lesha-spr.github.io/react-validation/)
11 | ### [DEMO src](https://github.com/Lesha-spr/react-validation/tree/master/src/App.js)
12 |
13 | It is just a validation and doesn't provide any model or something similar. You can use FormData or something like [form-serialize](https://www.npmjs.com/package/form-serialize) to get form data.
14 |
15 | ##### NOTE: Always pass the ```name``` props. It's required.
16 |
17 | Any additional props (such as event handlers) can also be passed to components.
18 |
19 | If you find any bug or error, please feel free to raise an issue. Pull requests are also welcome.
20 |
21 | ## Installation
22 |
23 | ``
24 | npm install react-validation
25 | ``
26 |
27 | ## Test
28 |
29 | ``
30 | npm test
31 | ``
32 |
33 | ## Example usage
34 |
35 | First of all let's define some validations:
36 |
37 | ```javascript
38 | import validator from 'validator';
39 | const required = (value) => {
40 | if (!value.toString().trim().length) {
41 | // We can return string or jsx as the 'error' prop for the validated Component
42 | return 'require';
43 | }
44 | };
45 |
46 | const email = (value) => {
47 | if (!validator.isEmail(value)) {
48 | return `${value} is not a valid email.`
49 | }
50 | };
51 |
52 | const lt = (value, props) => {
53 | // get the maxLength from component's props
54 | if (value.toString().trim().length > props.maxLength) {
55 | // Return jsx
56 | return The value exceeded {props.maxLength} symbols.
57 | }
58 | };
59 |
60 | const password = (value, props, components) => {
61 | // NOTE: Tricky place. The 'value' argument is always current component's value.
62 | // So in case we're 'changing' let's say 'password' component - we'll compare it's value with 'confirm' value.
63 | // But if we're changing 'confirm' component - the condition will always be true
64 | // If we need to always compare own values - replace 'value' with components.password[0].value and make some magic with error rendering.
65 | if (value !== components['confirm'][0].value) { // components['password'][0].value !== components['confirm'][0].value
66 | // 'confirm' - name of input
67 | // components['confirm'] - array of same-name components because of checkboxes and radios
68 | return Passwords are not equal.
69 | }
70 | };
71 | ```
72 |
73 | That's it. We can now use it in our React components:
74 |
75 | ```javascript
76 | import Form from 'react-validation/build/form';
77 | import Input from 'react-validation/build/input';
78 | import React, { Component } from 'react';
79 |
80 | export default class Login extends Component {
81 | render() {
82 | return
;
100 | }
101 | }
102 | ```
103 |
104 | Note the ```validations``` prop. It's an array of functions which was defined earlier.
105 |
106 | ## Components and props
107 |
108 | ```react-validation``` provides a ```components``` with pre-defined structure and ```hoc```s to define it self. The components are: ```Form```, ```Input```, ```Select```, ```Textarea``` and ```Button```.
109 | All of them are just custom wrappers around the native components. They can accept any valid attributes and a few extra:
110 |
111 | 1. ```isUsed``` - ```Input```, ```Select``` and ```Textarea```: says to react-validation to mark component as it was blured.
112 | 2. ```isChanged``` - ```Input```, ```Select``` and ```Textarea```: says to react-validation to mark component as it was changed.
113 | 3. ```validations``` - ```Input```, ```Select``` and ```Textarea```: accepts an array of validations functions.
114 |
115 | ##### NOTE: Always provide a ```name``` prop to ```Input```, ```Select``` and ```Textarea```.
116 |
117 | ### Form component
118 |
119 | ```
120 | Form
121 | ```
122 |
123 | The most important component, which provides the heart of react-validation. It basically mixes the binding between the form itself and child react-validation components via ```context```.
124 | Any valid props can easily be passed to ```Form```, such ```onSubmit``` and ```method```.
125 |
126 | ```Form``` provides four public methods:
127 |
128 | 1. ```validate(name)``` - validates control(s) with the passed name. The difference between this method and default validation is that ```validate``` marks the input as ```isUsed``` and ```isChanged```. ```name``` - name of the corresponding component(s).
129 |
130 | 2. ```showError(component [,error])``` - helps to handle async API errors. ```component``` - ref to the React Component to validate. ```error``` - error to show. Can be string or jsx.
131 |
132 | 3. ```hideError(component)``` - hides a corresponding component's error. ```component``` - ref to the React Component.
133 |
134 |
135 | ```javascript
136 | export default class Comment extends Component {
137 | handleSubmit = (event) => {
138 | event.preventDefault();
139 |
140 | // Emulate async API call
141 | setTimeout(() => {
142 | this.form.showError(this.userInput, API error );
143 | }, 1000);
144 | };
145 |
146 | removeApiError = () => {
147 | this.form.hideError(this.userInput);
148 | };
149 |
150 | render() {
151 | return
188 | }
189 | }
190 | ```
191 |
192 | ### HOCs
193 |
194 | react-validations also provides HOC (High Order Component) for each component. That made to have an ability to define own render logic, use mixed props, etc.
195 | ```javascript
196 | import { form, control, button } from 'react-validation';
197 |
198 | // Define own Form component
199 | const Form = ({ getValues, validate, showError, hideError, children, ...props }) => ( // destruct non-valid props
200 | {children}
201 | );
202 |
203 | // Define own Input component
204 | const Input = ({ error, isChanged, isUsed, ...props }) => (
205 |
206 |
207 | {isChanged && isUsed && error}
208 |
209 | );
210 |
211 | // Define own Button component
212 | const Button = ({ hasErrors, ...props }) => {
213 | return (
214 |
215 | );
216 | };
217 |
218 | // Now call HOCs on components
219 | const MyValidationForm = form(Form);
220 | const MyValidationInput = control(Input);
221 | const MyValidationButton = button(Button);
222 | ```
223 |
224 | That's it. Now MyValidationForm can be used with all given API.
225 |
226 | #### props
227 | ##### form:
228 | ```getValues``` - function which returns object with keys by 'name' prop and string values. NOTE: same-name controls will be returned as array of strings.
229 | ```validate(name)``` - function to validate controls by 'name' argument. It marks control as 'isUsed' and 'isBlured'.
230 | ```showError(component, [,error])``` - function to force showing error. component - ref to the control, error - string/jsx.
231 | ```hideError(component)``` - function to hide error on passed control ref.
232 |
233 | ##### control:
234 | ```error``` - string or jsx. Note that error will be defined anytime the control has invalid value. Use ```isUsed``` and ```isChanged``` to apply rendering logic.
235 | ```isChanged``` - boolean. Indicates the control was ```change```d.
236 | ```isUsed``` - boolean. Indicates the control was ```blur```d.
237 |
238 | ##### button:
239 | ```hasErrors``` - boolean. Indicates the whole form contain at least one invalid control.
240 |
241 | ### Input component
242 |
243 | ```
244 | Input
245 | ```
246 |
247 | A wrapper around the native ```input```. It accepts a ```validations``` prop - an array of functions.
248 |
249 | ```javascript
250 |
251 | ```
252 |
253 | `react-validation` will break with the first listed rule, if more than one rule is broken. In the example above (lt8 - value length less than 8), for ```really long value with d1g1t``` input value, the ```alpha``` rule will break validation first. We can control it by ordering rules within the ```validations``` array.
254 |
255 |
256 | ### Textarea component
257 |
258 | ```
259 | Textarea
260 | ```
261 |
262 | A wrapper around the native ```textarea```. Like ```Input```, it accepts a ```validations``` prop. Nothing special here:
263 |
264 | ```javascript
265 |
266 | ```
267 |
268 | ### Select component
269 |
270 | ```
271 | Select
272 | ```
273 |
274 | A wrapper around the native ```select```. Like ```Input```, it accepts a ```validations``` prop. Nothing special here:
275 |
276 | ```javascript
277 |
278 | Choose your city
279 | London
280 | Kyiv
281 | New York
282 |
283 | ```
284 |
285 | ### Button component
286 |
287 | ```
288 | Button
289 | ```
290 |
291 | A wrapper around the native ```button```. React-validation disables (adds ```disabled``` prop) the button on error occurrences.
292 |
--------------------------------------------------------------------------------
/config/webpack.config.prod.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const autoprefixer = require('autoprefixer');
4 | const path = require('path');
5 | const webpack = require('webpack');
6 | const HtmlWebpackPlugin = require('html-webpack-plugin');
7 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
8 | const ManifestPlugin = require('webpack-manifest-plugin');
9 | const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
10 | const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin');
11 | const eslintFormatter = require('react-dev-utils/eslintFormatter');
12 | const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
13 | const paths = require('./paths');
14 | const getClientEnvironment = require('./env');
15 |
16 | // Webpack uses `publicPath` to determine where the app is being served from.
17 | // It requires a trailing slash, or the file assets will get an incorrect path.
18 | const publicPath = paths.servedPath;
19 | // Some apps do not use client-side routing with pushState.
20 | // For these, "homepage" can be set to "." to enable relative asset paths.
21 | const shouldUseRelativeAssetPaths = publicPath === './';
22 | // Source maps are resource heavy and can cause out of memory issue for large source files.
23 | const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
24 | // `publicUrl` is just like `publicPath`, but we will provide it to our app
25 | // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript.
26 | // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz.
27 | const publicUrl = publicPath.slice(0, -1);
28 | // Get environment variables to inject into our app.
29 | const env = getClientEnvironment(publicUrl);
30 |
31 | // Assert this just to be safe.
32 | // Development builds of React are slow and not intended for production.
33 | if (env.stringified['process.env'].NODE_ENV !== '"production"') {
34 | throw new Error('Production builds must have NODE_ENV=production.');
35 | }
36 |
37 | // Note: defined here because it will be used more than once.
38 | const cssFilename = 'static/css/[name].[contenthash:8].css';
39 |
40 | // ExtractTextPlugin expects the build output to be flat.
41 | // (See https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/27)
42 | // However, our output is structured with css, js and media folders.
43 | // To have this structure working with relative paths, we have to use custom options.
44 | const extractTextPluginOptions = shouldUseRelativeAssetPaths
45 | ? // Making sure that the publicPath goes back to to build folder.
46 | { publicPath: Array(cssFilename.split('/').length).join('../') }
47 | : {};
48 |
49 | // This is the production configuration.
50 | // It compiles slowly and is focused on producing a fast and minimal bundle.
51 | // The development configuration is different and lives in a separate file.
52 | module.exports = {
53 | // Don't attempt to continue if there are any errors.
54 | bail: true,
55 | // We generate sourcemaps in production. This is slow but gives good results.
56 | // You can exclude the *.map files from the build during deployment.
57 | devtool: shouldUseSourceMap ? 'source-map' : false,
58 | // In production, we only want to load the polyfills and the app code.
59 | // entry: [require.resolve('./polyfills'), paths.appLibJs, paths.appFormJs, paths.appInputJs, paths.appSelectJs, paths.appTextareaJs, paths.appButtonJs],
60 | entry: { polyfills: require.resolve('./polyfills'), main: paths.appLibJs, form: paths.appFormJs, input: paths.appInputJs, select: paths.appSelectJs, textarea: paths.appTextareaJs, button: paths.appButtonJs},
61 | output: {
62 | library: "[name]",
63 | libraryTarget: "umd",
64 | // The build folder.
65 | path: paths.appBuild,
66 | // Generated JS file names (with nested folders).
67 | // There will be one main bundle, and one file per asynchronous chunk.
68 | // We don't currently advertise code splitting but Webpack supports it.
69 | filename: '[name].js',
70 | // We inferred the "public path" (such as / or /my-project) from homepage.
71 | publicPath: publicPath,
72 | // Point sourcemap entries to original disk location (format as URL on Windows)
73 | devtoolModuleFilenameTemplate: info =>
74 | path
75 | .relative(paths.appSrc, info.absoluteResourcePath)
76 | .replace(/\\/g, '/'),
77 | },
78 | externals: {
79 | "react": {
80 | commonjs: "react",
81 | commonjs2: "react",
82 | amd: "react",
83 | root: "React"
84 | },
85 | "lodash.omit": {
86 | commonjs: "lodash.omit",
87 | commonjs2: "lodash.omit",
88 | amd: "lodash.omit",
89 | root: "_.omit"
90 | },
91 | "prop-types": {
92 | commonjs: "prop-types",
93 | commonjs2: "prop-types",
94 | amd: "prop-types",
95 | root: "PropTypes"
96 | },
97 | "uuid/v4": {
98 | commonjs: "uuid/v4",
99 | commonjs2: "uuid/v4",
100 | amd: "uuid/v4",
101 | root: "uuid"
102 | }
103 | },
104 | resolve: {
105 | // This allows you to set a fallback for where Webpack should look for modules.
106 | // We placed these paths second because we want `node_modules` to "win"
107 | // if there are any conflicts. This matches Node resolution mechanism.
108 | // https://github.com/facebookincubator/create-react-app/issues/253
109 | modules: ['node_modules', paths.appNodeModules].concat(
110 | // It is guaranteed to exist because we tweak it in `env.js`
111 | process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
112 | ),
113 | // These are the reasonable defaults supported by the Node ecosystem.
114 | // We also include JSX as a common component filename extension to support
115 | // some tools, although we do not recommend using it, see:
116 | // https://github.com/facebookincubator/create-react-app/issues/290
117 | // `web` extension prefixes have been added for better support
118 | // for React Native Web.
119 | extensions: ['.web.js', '.js', '.json', '.web.jsx', '.jsx'],
120 | alias: {
121 |
122 | // Support React Native Web
123 | // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
124 | 'react-native': 'react-native-web',
125 | },
126 | plugins: [
127 | // Prevents users from importing files from outside of src/ (or node_modules/).
128 | // This often causes confusion because we only process files within src/ with babel.
129 | // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
130 | // please link the files into your node_modules/ and let module-resolution kick in.
131 | // Make sure your source files are compiled, as they will not be processed in any way.
132 | new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
133 | ],
134 | },
135 | module: {
136 | strictExportPresence: true,
137 | rules: [
138 | // TODO: Disable require.ensure as it's not a standard language feature.
139 | // We are waiting for https://github.com/facebookincubator/create-react-app/issues/2176.
140 | // { parser: { requireEnsure: false } },
141 |
142 | // First, run the linter.
143 | // It's important to do this before Babel processes the JS.
144 | {
145 | test: /\.(js|jsx)$/,
146 | enforce: 'pre',
147 | use: [
148 | {
149 | options: {
150 | formatter: eslintFormatter,
151 | eslintPath: require.resolve('eslint'),
152 |
153 | },
154 | loader: require.resolve('eslint-loader'),
155 | },
156 | ],
157 | include: paths.appSrc,
158 | },
159 | {
160 | // "oneOf" will traverse all following loaders until one will
161 | // match the requirements. When no loader matches it will fall
162 | // back to the "file" loader at the end of the loader list.
163 | oneOf: [
164 | // "url" loader works just like "file" loader but it also embeds
165 | // assets smaller than specified size as data URLs to avoid requests.
166 | {
167 | test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
168 | loader: require.resolve('url-loader'),
169 | options: {
170 | limit: 10000,
171 | name: 'static/media/[name].[hash:8].[ext]',
172 | },
173 | },
174 | // Process JS with Babel.
175 | {
176 | test: /\.(js|jsx)$/,
177 | include: paths.appSrc,
178 | loader: require.resolve('babel-loader'),
179 | options: {
180 |
181 | compact: true,
182 | },
183 | },
184 | // The notation here is somewhat confusing.
185 | // "postcss" loader applies autoprefixer to our CSS.
186 | // "css" loader resolves paths in CSS and adds assets as dependencies.
187 | // "style" loader normally turns CSS into JS modules injecting