@unbxd-ui/unbxd-react-components 0.2.99 → 0.2.101-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/.babelrc +4 -0
  2. package/.eslintrc.js +38 -0
  3. package/CONTRIBUTE.md +105 -0
  4. package/components/Form/RangeSlider.js +3 -7
  5. package/components/core.css +1 -3
  6. package/components/theme.css +0 -2
  7. package/package.json +23 -13
  8. package/src/Intro.stories.mdx +119 -0
  9. package/src/components/Accordian/Accordian.js +89 -0
  10. package/src/components/Accordian/Accordian.stories.js +92 -0
  11. package/src/components/Accordian/accordianCore.scss +8 -0
  12. package/src/components/Accordian/accordianTheme.scss +6 -0
  13. package/src/components/Accordian/index.js +3 -0
  14. package/src/components/Button/Button.js +67 -0
  15. package/src/components/Button/Button.stories.js +103 -0
  16. package/src/components/Button/DropdownButton.js +60 -0
  17. package/src/components/Button/DropdownButton.stories.js +38 -0
  18. package/src/components/Button/buttonTheme.css +1 -0
  19. package/src/components/Button/buttonTheme.scss +45 -0
  20. package/src/components/Button/index.js +5 -0
  21. package/src/components/DataLoader/DataLoader.js +86 -0
  22. package/src/components/DataLoader/DataLoader.stories.js +72 -0
  23. package/src/components/DataLoader/index.js +3 -0
  24. package/src/components/Form/Checkbox.js +73 -0
  25. package/src/components/Form/DragDropFileUploader.js +67 -0
  26. package/src/components/Form/Dropdown.js +415 -0
  27. package/src/components/Form/FileUploader.js +64 -0
  28. package/src/components/Form/Form.js +83 -0
  29. package/src/components/Form/FormElementWrapper.js +22 -0
  30. package/src/components/Form/Input.js +121 -0
  31. package/src/components/Form/RadioList.js +86 -0
  32. package/src/components/Form/RangeSlider.js +100 -0
  33. package/src/components/Form/ServerPaginatedDDList.js +226 -0
  34. package/src/components/Form/Textarea.js +76 -0
  35. package/src/components/Form/Toggle.js +96 -0
  36. package/src/components/Form/form.css +1 -0
  37. package/src/components/Form/formCore.scss +142 -0
  38. package/src/components/Form/formTheme.scss +27 -0
  39. package/src/components/Form/index.js +13 -0
  40. package/src/components/Form/stories/Checkbox.stories.js +41 -0
  41. package/src/components/Form/stories/DragDropFileUploader.stories.js +21 -0
  42. package/src/components/Form/stories/Dropdown.stories.js +124 -0
  43. package/src/components/Form/stories/FileUploader.stories.js +21 -0
  44. package/src/components/Form/stories/FormDefault.stories.js +87 -0
  45. package/src/components/Form/stories/RadioList.stories.js +48 -0
  46. package/src/components/Form/stories/RangeSlider.stories.js +84 -0
  47. package/src/components/Form/stories/TextInput.stories.js +77 -0
  48. package/src/components/Form/stories/Textarea.stories.js +43 -0
  49. package/src/components/Form/stories/Toggle.stories.js +14 -0
  50. package/src/components/Form/stories/form.stories.js +216 -0
  51. package/src/components/InlineModal/InlineModal.js +135 -0
  52. package/src/components/InlineModal/InlineModal.stories.js +54 -0
  53. package/src/components/InlineModal/index.js +4 -0
  54. package/src/components/InlineModal/inlineModal.css +1 -0
  55. package/src/components/InlineModal/inlineModalCore.scss +31 -0
  56. package/src/components/InlineModal/inlineModalTheme.scss +16 -0
  57. package/src/components/List/List.js +72 -0
  58. package/src/components/List/index.js +3 -0
  59. package/src/components/List/list.stories.js +28 -0
  60. package/src/components/List/listCore.css +1 -0
  61. package/src/components/List/listCore.scss +6 -0
  62. package/src/components/Modal/Modal.js +99 -0
  63. package/src/components/Modal/Modal.stories.js +54 -0
  64. package/src/components/Modal/index.js +3 -0
  65. package/src/components/Modal/modal.css +1 -0
  66. package/src/components/Modal/modalCore.scss +34 -0
  67. package/src/components/NotificationComponent/NotificationComponent.js +58 -0
  68. package/src/components/NotificationComponent/NotificationComponent.stories.js +28 -0
  69. package/src/components/NotificationComponent/index.js +3 -0
  70. package/src/components/NotificationComponent/notificationComponent.css +1 -0
  71. package/src/components/NotificationComponent/notificationTheme.scss +30 -0
  72. package/src/components/ProgressBar/ProgressBar.js +45 -0
  73. package/src/components/ProgressBar/ProgressBar.stories.js +14 -0
  74. package/src/components/ProgressBar/index.js +3 -0
  75. package/src/components/ProgressBar/progressBarCore.css +1 -0
  76. package/src/components/ProgressBar/progressBarCore.scss +14 -0
  77. package/src/components/ProgressBar/progressBarTheme.css +0 -0
  78. package/src/components/ProgressBar/progressBarTheme.scss +0 -0
  79. package/src/components/Table/BaseTable.js +306 -0
  80. package/src/components/Table/PaginationComponent.js +73 -0
  81. package/src/components/Table/Table.js +295 -0
  82. package/src/components/Table/Table.stories.js +198 -0
  83. package/src/components/Table/index.js +8 -0
  84. package/src/components/Table/table.css +1 -0
  85. package/src/components/Table/tableCore.scss +94 -0
  86. package/src/components/Table/tableTheme.scss +34 -0
  87. package/src/components/TabsComponent/TabsComponent.js +99 -0
  88. package/src/components/TabsComponent/TabsComponent.stories.js +69 -0
  89. package/src/components/TabsComponent/index.js +3 -0
  90. package/src/components/TabsComponent/tabs.css +1 -0
  91. package/src/components/TabsComponent/tabsCore.scss +59 -0
  92. package/src/components/TabsComponent/tabsTheme.css +0 -0
  93. package/src/components/TabsComponent/tabsTheme.scss +0 -0
  94. package/src/components/Tooltip/Tooltip.js +87 -0
  95. package/src/components/Tooltip/Tooltip.stories.js +16 -0
  96. package/src/components/Tooltip/index.js +3 -0
  97. package/src/components/Tooltip/tooltipCore.scss +22 -0
  98. package/src/components/Tooltip/tooltipTheme.scss +21 -0
  99. package/src/components/core.css +1 -0
  100. package/src/components/core.scss +29 -0
  101. package/src/components/index.js +38 -0
  102. package/src/components/theme.css +1 -0
  103. package/src/components/theme.scss +11 -0
  104. package/src/core/Validators.js +34 -0
  105. package/src/core/customHooks.js +20 -0
  106. package/src/core/dataLoader.js +143 -0
  107. package/src/core/dataLoader.stories.js +123 -0
  108. package/src/core/index.js +3 -0
  109. package/src/core/utils.js +95 -0
  110. package/src/index.js +68 -0
  111. package/vscode-templates/NewStoryTemplate.stories.js +8 -0
  112. package/core/Validators.js +0 -48
  113. package/core/customHooks.js +0 -41
  114. package/core/dataLoader.js +0 -235
  115. package/core/dataLoader.stories.js +0 -153
  116. package/core/index.js +0 -31
  117. package/core/utils.js +0 -112
  118. package/index.js +0 -193
  119. /package/{Readme.md → README.md} +0 -0
  120. /package/{components → src/components}/Accordian/accordianCore.css +0 -0
  121. /package/{components → src/components}/Accordian/accordianTheme.css +0 -0
  122. /package/{components/Button/buttonTheme.css → src/components/Button/button.css} +0 -0
  123. /package/{components → src/components}/Form/formCore.css +0 -0
  124. /package/{components → src/components}/Form/formTheme.css +0 -0
  125. /package/{components → src/components}/InlineModal/inlineModalCore.css +0 -0
  126. /package/{components → src/components}/InlineModal/inlineModalTheme.css +0 -0
  127. /package/{components/List/listCore.css → src/components/List/list.css} +0 -0
  128. /package/{components → src/components}/List/listTheme.css +0 -0
  129. /package/{components/Modal/modalTheme.css → src/components/List/listTheme.scss} +0 -0
  130. /package/{components → src/components}/Modal/modalCore.css +0 -0
  131. /package/{components/ProgressBar/progressBarTheme.css → src/components/Modal/modalTheme.css} +0 -0
  132. /package/{components/TabsComponent/tabsTheme.css → src/components/Modal/modalTheme.scss} +0 -0
  133. /package/{components → src/components}/NotificationComponent/notificationTheme.css +0 -0
  134. /package/{components/ProgressBar/progressBarCore.css → src/components/ProgressBar/progressBar.css} +0 -0
  135. /package/{components → src/components}/Table/tableCore.css +0 -0
  136. /package/{components → src/components}/Table/tableTheme.css +0 -0
  137. /package/{components → src/components}/TabsComponent/tabsCore.css +0 -0
  138. /package/{components → src/components}/Tooltip/tooltipCore.css +0 -0
  139. /package/{components → src/components}/Tooltip/tooltipTheme.css +0 -0
@@ -0,0 +1,22 @@
1
+ .RCB {
2
+ &-tooltip {
3
+ display: inline-block;
4
+ position: relative;
5
+
6
+ .RCB-tooltip-body {
7
+ &.RCB-tooltip-hover {
8
+ display: inline-block;
9
+ }
10
+
11
+ &.RCB-tooltip-click {
12
+ display: inline-block;
13
+ }
14
+ }
15
+ }
16
+
17
+ &-tooltip-body {
18
+ display: none;
19
+ position: absolute;
20
+ z-index: 1;
21
+ }
22
+ }
@@ -0,0 +1,21 @@
1
+ .RCB {
2
+ &-tooltip-btn {
3
+ display: inline-block;
4
+ font-style: italic;
5
+ font-size: 12px;
6
+ color: #9199AA;
7
+ background-color: #F8FAFB;
8
+ border: 1px solid #D0DDE2;
9
+ padding: 0px 6px;
10
+ border-radius: 50%;
11
+ text-align: center;
12
+ }
13
+
14
+ &-tooltip-body {
15
+ background: #FFF;
16
+ padding: 10px;
17
+ border-radius: 4px;
18
+ box-shadow: 0px 1px 7px 0px #ccc;
19
+ margin-left: 15px;
20
+ }
21
+ }
@@ -0,0 +1 @@
1
+ .RCB-form-el-inline{margin:20px 0;display:inline-block}.RCB-form-el-inline .RCB-form-el-label{margin-right:15px}.RCB-form-el-inline .RCB-toggle{display:inline-block}.RCB-form-el-block{margin:20px 0}.RCB-form-el-block .RCB-form-el-label{display:block}.RCB-dropdown .RCB-list-item{list-style-type:none;padding:10px;cursor:pointer}.RCB-dropdown .RCB-list-item:hover{background-color:#eee}.RCB-dropdown .RCB-list-item.selected{background-color:#eee}.RCB-dd-with-create .RCB-inline-modal-body{display:flex;flex-direction:column}.RCB-dd-with-create .RCB-inline-modal-body .RCB-list{flex:1;overflow:scroll}.RCB-dd-with-create .RCB-dd-create-cta{padding:10px;text-align:center;border:1px solid #bfbfbf;cursor:pointer}.RCB-clear-selected{background:#f2f0f0;padding:3px 6px;font-size:11px;border-radius:15px;border:1px solid #ccc}.RCB-selection-wrapper{float:right}.RCB-selection-wrapper .RCB-select-arrow{float:unset}.RCB-select-arrow{float:right;font-size:12px;color:#96a9bc;margin-right:12px;margin-left:8px}.RCB-select-arrow:after{content:"\25BC";vertical-align:middle}.RCB-dd-label{display:inline-block;overflow:hidden;text-overflow:ellipsis;max-width:70%;vertical-align:top;white-space:nowrap}.RCB-file-input{cursor:pointer}.RCB-drag-drop-uploader{border:2px dashed rgba(104,128,145,0.42);padding:20px;text-align:center}.RCB-drag-over{background:#f3f3f3}.RCB-toggle{padding:2px 3px;background-color:#FFF;border:1px solid #CCC;border-radius:20px;box-sizing:content-box;cursor:pointer}.RCB-toggle.active{background-color:#2cb191}.RCB-toggle.active .RCB-toggle-knob{background-color:#FFF}.RCB-toggle-disable{cursor:not-allowed;opacity:0.8}.RCB-toggle-knob{background-color:#8399ae;border-radius:50%;-webkit-transition:transform .3s ease;-moz-transition:transform .3s ease;-ms-transition:transform .3s ease;transition:transform .3s ease}.RCB-modal{position:fixed;top:0;width:100%;height:100%;background:rgba(0,0,0,0.8);display:flex;justify-content:center;align-items:center;z-index:2}.RCB-modal-body{background:#FFF;padding:20px}.RCB-modal-header{display:flex;margin-bottom:10px}.RCB-modal-title{flex:1}.RCB-modal-close{cursor:pointer}.RCB-modal-close:before{content:"X"}.RCB-inline-modal{position:relative;display:inline-block}.RCB-inline-modal.hover-open .RCB-inline-modal-body{display:none}.RCB-inline-modal.hover-open:hover .RCB-inline-modal-body{display:block}.RCB-inline-modal-body{position:absolute;z-index:1}.RCB-inline-modal-body.RCB-align-left{left:0}.RCB-inline-modal-body.RCB-align-right{right:0}.RCB-list{margin:0;padding:0}.RCB-table{border-collapse:collapse;width:100%}.RCB-th.RCB-expand-column{width:50px}.RCB-th-sortable{cursor:pointer}.RCB-th-sort:after{content:"\2B0D"}.RCB-th-asc:after{content:"\25B2"}.RCB-th-dsc:after{content:"\25BC"}.RCB-tr .expand-open:before{content:"▼"}.RCB-tr .expand-close:before{content:"▶"}.RCB-paginate-wrapper .RCB-per-page-count{display:inline-block}.RCB-paginate-wrapper .RCB-form-el-cont{margin:0}.RCB-paginate-wrapper .RCB-inline-modal-btn{background:transparent;padding:0}.RCB-paginate-nav{display:inline-block;border-radius:12px;border:solid 1px #8399ae;background-color:#f6f7f9;vertical-align:middle;margin-left:15px;overflow:hidden}.RCB-page-nav{padding:0 5px;text-decoration:none;color:inherit}.RCB-page-nav:first-child{border-right:solid 1px #8399ae}.RCB-page-nav.disabled{color:#ccc;pointer-events:none;cursor:not-allowed}.RCB-no-data{text-align:center}.RCB-tabs-container{display:flex}.RCB-tab-title{list-style-type:none;padding:10px;cursor:pointer}.RCB-tab-title.selected{background:#FFF;font-weight:bold;border:1px solid #cacaca;position:relative;z-index:1}.RCB-tabs-horizontal{flex-direction:column}.RCB-tabs-horizontal .RCB-tab-title{display:inline-block}.RCB-tabs-horizontal .RCB-tab-title.selected{border-bottom:0;bottom:-1px}.RCB-tabs-vertical .RCB-tab-title{display:block}.RCB-tabs-vertical .RCB-tab-title.selected{border-right:0;right:-1px}.RCB-tab-content{list-style-type:none;border:1px solid #cacaca;padding:10px}.RCB-tab-content.selected{display:block}.RCB-tab-disabled{pointer-events:none;cursor:not-allowed;color:#ccc}.RCB-progress-bar{width:100%;position:relative;background:#ccc}.RCB-progress-value{height:100%;position:absolute;top:0;background:#3d9565}.RCB-tooltip{display:inline-block;position:relative}.RCB-tooltip .RCB-tooltip-body.RCB-tooltip-hover{display:inline-block}.RCB-tooltip .RCB-tooltip-body.RCB-tooltip-click{display:inline-block}.RCB-tooltip-body{display:none;position:absolute;z-index:1}.RCB-accordian-title{cursor:pointer}.RCB-list{list-style-type:none}.RCB-hidden{display:none}.RCB-no-pointer{pointer-events:none}.RCB-disabled .RCB-inline-modal-btn{cursor:not-allowed;pointer-events:none}
@@ -0,0 +1,29 @@
1
+ /**
2
+ Add all the styles here without which the component behaviour would be meaningless
3
+ & hence these styles are must haves for anyone using the component
4
+ **/
5
+
6
+ @import "./Form/formCore.scss";
7
+ @import "./Modal/modalCore.scss";
8
+ @import "./InlineModal/inlineModalCore.scss";
9
+ @import "./List/listCore.scss";
10
+ @import "./Table/tableCore.scss";
11
+ @import "./TabsComponent/tabsCore.scss";
12
+ @import "./ProgressBar/progressBarCore.scss";
13
+ @import "./Tooltip/tooltipCore.scss";
14
+ @import "./Accordian/accordianCore.scss";
15
+
16
+ .RCB-hidden {
17
+ display: none;
18
+ }
19
+
20
+ .RCB-no-pointer {
21
+ pointer-events: none;
22
+ }
23
+
24
+ .RCB-disabled {
25
+ .RCB-inline-modal-btn {
26
+ cursor: not-allowed;
27
+ pointer-events: none;
28
+ }
29
+ }
@@ -0,0 +1,38 @@
1
+ import Button, { DropdownButton } from "./Button";
2
+ import List from "./List";
3
+ import Modal from "./Modal";
4
+ import InlineModal from "./InlineModal";
5
+ import DataLoader from "./DataLoader";
6
+ import Form, { Input, Textarea, Checkbox, RadioList, Dropdown, RangeSlider, FileUploader, DragDropFileUploader, Toggle } from "./Form";
7
+ import Table , { PaginationComponent } from "./Table";
8
+ import TabsComponent from "./TabsComponent";
9
+ import NotificationComponent from "./NotificationComponent";
10
+ import ProgressBar from "./ProgressBar";
11
+ import Tooltip from "./Tooltip";
12
+ import Accordian from "./Accordian";
13
+
14
+ export {
15
+ Button,
16
+ DropdownButton,
17
+ List,
18
+ Modal,
19
+ InlineModal,
20
+ DataLoader,
21
+ Form,
22
+ Input,
23
+ Textarea,
24
+ Checkbox,
25
+ RadioList,
26
+ Dropdown,
27
+ RangeSlider,
28
+ FileUploader,
29
+ DragDropFileUploader,
30
+ Toggle,
31
+ Table,
32
+ PaginationComponent,
33
+ TabsComponent,
34
+ NotificationComponent,
35
+ ProgressBar,
36
+ Tooltip,
37
+ Accordian
38
+ };
@@ -0,0 +1 @@
1
+ .RCB-btn{border-radius:3px;cursor:pointer}.RCB-btn-default:hover{background:#f3f3f3}.RCB-btn-primary{background:#1fa7fd;color:#FFF;border:0}.RCB-btn-primary:hover{background:#208dd2}.RCB-btn-secondary{background:#FFF;border:1px solid #95c7e7}.RCB-btn-secondary:hover{background:#eef8ff}.RCB-btn-small{padding:6px 8px}.RCB-btn-medium{padding:10px 15px}.RCB-btn-large{padding:15px 22px}.RCB-form-error{font-size:12px;color:#d25b5b}.RCB-dd-search{position:relative}.RCB-dd-search-icon{position:absolute;top:5px;left:10px}.RCB-dd-search-icon:before{content:"\1F50D"}.RCB-dd-search-ip{width:100%;padding:10px 30px;border:none;border-bottom:1px solid #CCC}.RCB-inline-modal-btn{display:inline-block;background:#FFF;border:1px solid #eee;padding:10px;border-radius:3px;cursor:pointer}.RCB-inline-modal-body{background:#FFF;border:1px solid #efeeee;box-shadow:0 9px 12px 0 rgba(0,0,0,0.15)}.RCB-notif{padding:10px;border-radius:3px}.RCB-notif-success{color:#129274;border:solid 1px #2cb191;background-color:#edfffb}.RCB-notif-error{color:#d25b5b;border:solid 1px #e75178;background-color:#fff3f6}.RCB-notif-warning{color:#445870;border:solid 1px #efbf6a;background-color:#fffaf2}.RCB-notif-info{color:#509DB9;border:solid 1px #45b5c1;background-color:#f4fcff}.RCB-table td{padding:10px}.RCB-th{background-color:#2287b4;color:#FFF;font-weight:normal;padding:10px}.RCB-even-tr{background-color:#FFF}.RCB-odd-tr{background-color:#dcf1fa}.RCB-expanded-row{background-color:#ecf2f4}.RCB-paginate-bar{background-color:#a3c9db;text-align:right;font-size:14px;padding:5px;border-radius:5px 5px 0 0}.RCB-tooltip-btn{display:inline-block;font-style:italic;font-size:12px;color:#9199AA;background-color:#F8FAFB;border:1px solid #D0DDE2;padding:0px 6px;border-radius:50%;text-align:center}.RCB-tooltip-body{background:#FFF;padding:10px;border-radius:4px;box-shadow:0px 1px 7px 0px #ccc;margin-left:15px}.RCB-accordian-title{padding:10px;border:1px solid #ccc}
@@ -0,0 +1,11 @@
1
+ /**
2
+ Add all the styles here which suggests a theme for the component but is not a must have to use the component
3
+ **/
4
+
5
+ @import "./Button/buttonTheme.scss";
6
+ @import "./Form/formTheme.scss";
7
+ @import "./InlineModal/inlineModalTheme.scss";
8
+ @import "./NotificationComponent/notificationTheme.scss";
9
+ @import "./Table/tableTheme.scss";
10
+ @import "./Tooltip/tooltipTheme.scss";
11
+ @import "./Accordian/accordianTheme.scss";
@@ -0,0 +1,34 @@
1
+ import utils from "./utils";
2
+
3
+ const VALIDATORS = {
4
+ EMAIL: (value = "") => {
5
+ const regEx = /^[_A-Za-z0-9-+]+(\.[_A-Za-z0-9-\\+]+)*@[_A-Za-z0-9-+]+(\.[_A-Za-z0-9-+]+)*(\.[A-Za-z]{2,})$/i;
6
+ return regEx.test(value.trim());
7
+ },
8
+ NUMERIC: (value = "") => {
9
+ const regEx = /^\d+$/;
10
+ const numValue = +value;
11
+ return regEx.test(numValue);
12
+ },
13
+ ALPHA_NUMERIC: (value = "") => {
14
+ const regEx = /^[A-Za-z0-9]+$/;
15
+ return regEx.test(value.trim());
16
+ },
17
+ URL: (value = "") => {
18
+ const regEx = /^(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-/]))?$/i;
19
+ return regEx.test(value.trim());
20
+ },
21
+ REQUIRED: (value) => {
22
+ if ((utils.isArray(value) && value.length == 0)
23
+ || (value !== 0 && !value)) {
24
+ return false;
25
+ }
26
+ return true;
27
+ },
28
+ CUSTOM: (value, validationObj) => {
29
+ const { validator = () => {} } = validationObj;
30
+ return validator.call(null, value, validationObj);
31
+ }
32
+ };
33
+
34
+ export default VALIDATORS;
@@ -0,0 +1,20 @@
1
+ import { useState, useEffect, useRef, useCallback } from "react";
2
+
3
+ export function useDidUpdateEffect(fn, inputs) {
4
+ const didMountRef = useRef(false);
5
+
6
+ useEffect(() => {
7
+ if (didMountRef.current)
8
+ fn();
9
+ else
10
+ didMountRef.current = true;
11
+ }, inputs);
12
+ }
13
+
14
+ export function useForceUpdate() {
15
+ const [, setTick] = useState(0);
16
+ const update = useCallback(() => {
17
+ setTick(tick => tick + 1);
18
+ }, []);
19
+ return update;
20
+ }
@@ -0,0 +1,143 @@
1
+ import { Promise } from "bluebird";
2
+ import { fetch as fetchPolyfill } from "whatwg-fetch";
3
+ import utils from "./utils";
4
+
5
+ const UNAUTHORIZED = 401,
6
+ NOT_FOUND = 404;
7
+
8
+ class DataLoader {
9
+ _requestsMap = {}
10
+ _commonHeaders = {}
11
+ _responseParser = x => x
12
+ _requestParser = x => x
13
+ _exceptionHandler = x => x
14
+ _middlewares = {}
15
+ setCommonHeaders (headers) {
16
+ this._commonHeaders = {...this._commonHeaders, ...headers};
17
+ }
18
+ setResponseParser (responseParser) {
19
+ this._responseParser = responseParser;
20
+ }
21
+ setRequestParser (requestParser) {
22
+ this._requestParser = requestParser;
23
+ }
24
+ setExceptionHandler (exceptionHandler) {
25
+ this._exceptionHandler = exceptionHandler;
26
+ }
27
+ addRequestConfig (requestId, requestConfig) {
28
+ this._requestsMap[requestId] = requestConfig;
29
+ }
30
+ getRequestMiddleware (requestId) {
31
+ let requestMiddleware = x => x,
32
+ middleware = this._middlewares[requestId];
33
+
34
+ if (typeof(middleware) !== "undefined" && typeof(middleware.reqParser) === "function") {
35
+ requestMiddleware = middleware.reqParser;
36
+ }
37
+
38
+ return requestMiddleware;
39
+ }
40
+ getResponseMiddleware (requestId) {
41
+ let responseMiddleware = x => x,
42
+ middleware = this._middlewares[requestId];
43
+
44
+ if (typeof(middleware) !== "undefined" && typeof(middleware.resParser) === "function") {
45
+ responseMiddleware = middleware.resParser;
46
+ }
47
+
48
+ return responseMiddleware;
49
+ }
50
+ getRequestParams (requestId, params) {
51
+ const requestParser = this.getRequestMiddleware(requestId);
52
+ return requestParser(params, requestId);
53
+ }
54
+ parseResponseData (requestId, response, headers, status) {
55
+ const responseParser = this.getResponseMiddleware(requestId);
56
+ const commonParser = this._responseParser;
57
+ /* parse through common parser */
58
+ response = typeof(commonParser) === "function" ? commonParser(response, requestId, headers, status) : response;
59
+ return responseParser(response, requestId, headers, status);
60
+ }
61
+ getRequestDef ({ requestId, urlParams = {}, params = {}, headers = {} }) {
62
+ const requestConfig = this._requestsMap[requestId];
63
+ const { url, method = "GET" } = requestConfig;
64
+ const finalRequestParams = this.getRequestParams(requestId, params);
65
+
66
+ let requestUrl = (typeof(url) === "function") ? url(urlParams) : url;
67
+ let reqMethod = method.toLowerCase();
68
+
69
+ let requestMetadata = {
70
+ method: (reqMethod === "form_post" || reqMethod === "upload") ? "post" : method,
71
+ headers: {...this._commonHeaders, ...headers}
72
+ };
73
+
74
+ const requestHeaders = requestMetadata.headers;
75
+
76
+ for (let header in requestHeaders) {
77
+ if (requestHeaders[header] === null) {
78
+ /* if header is set as null, delete it from the headers list */
79
+ delete requestHeaders[header];
80
+ }
81
+ }
82
+
83
+ if (reqMethod === "get") {
84
+ requestUrl = `${requestUrl}?${utils.getQueryParams(finalRequestParams)}`;
85
+ } else if (["post", "delete", "put", "patch"].indexOf(reqMethod) > -1) {
86
+ requestMetadata.body = JSON.stringify(finalRequestParams);
87
+ } else if (reqMethod === "form_post" || reqMethod === "upload") {
88
+ const formData = new FormData();
89
+ for (const key in finalRequestParams) {
90
+ formData.append(key, finalRequestParams[key]);
91
+ }
92
+ requestMetadata.body = formData;
93
+ delete requestHeaders["Content-Type"];
94
+ }
95
+
96
+ return new Promise((resolve, reject) => {
97
+ return fetchPolyfill(requestUrl, requestMetadata)
98
+ .then(response => {
99
+ const { status, statusText, headers } = response;
100
+
101
+ if (status === UNAUTHORIZED || status === NOT_FOUND) {
102
+ this._exceptionHandler(response);
103
+ reject(response);
104
+ } else {
105
+ const stringStatus = status.toString();
106
+ if (stringStatus.indexOf("2") === 0 || stringStatus.indexOf("4") === 0) {
107
+ /* Success : 2** response code, or 4** response code */
108
+ return response.json().then((data) => {
109
+ return {
110
+ headers: headers,
111
+ status: status,
112
+ json: data
113
+ }
114
+ })
115
+ } else {
116
+ this._exceptionHandler(statusText);
117
+ reject(statusText);
118
+ }
119
+ }
120
+ })
121
+ .then(({headers, json, status}) => {
122
+ const parsedResponse = this.parseResponseData(requestId, json, headers, status);
123
+ resolve(parsedResponse);
124
+ })
125
+ .catch(exception => {
126
+ this._exceptionHandler(exception);
127
+ reject(exception);
128
+ });
129
+ });
130
+ }
131
+ addMiddleware (requestId, { requestParser, responseParser }) {
132
+ if (typeof(this._middlewares[requestId]) !== "undefined") {
133
+ throw new Error(`Middleware for ${requestId} already exists`);
134
+ }
135
+
136
+ this._middlewares[requestId] = {
137
+ reqParser: requestParser,
138
+ resParser: responseParser
139
+ };
140
+ }
141
+ }
142
+
143
+ export default new DataLoader();
@@ -0,0 +1,123 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import dataLoader from "./dataLoader";
3
+ import List from "../components/List";
4
+
5
+ dataLoader.addRequestConfig("getUsers", {
6
+ method: "GET",
7
+ url: "https://jsonplaceholder.typicode.com/users",
8
+ });
9
+
10
+ dataLoader.addRequestConfig("getTodo", {
11
+ method: "GET",
12
+ url: function(params) {
13
+ return `https://jsonplaceholder.typicode.com/todos/${params.todoId}`
14
+ }
15
+ });
16
+
17
+ dataLoader.addRequestConfig("getPost", {
18
+ method: "GET",
19
+ url: function(params) {
20
+ return `https://jsonplaceholder.typicode.com/posts/${params.id}`
21
+ }
22
+ });
23
+
24
+ export const SimpleUsage = () => {
25
+ const [ data, setData ] = useState([]);
26
+
27
+ useEffect(() => {
28
+ const def = dataLoader.getRequestDef({
29
+ requestId: "getUsers"
30
+ });
31
+
32
+ def.done((response) => {
33
+ setData(response);
34
+ });
35
+
36
+ def.catch((e) => {
37
+ console.error(e);
38
+ });
39
+ }, []);
40
+
41
+ return (<div>
42
+ <p>Use the <code>dataLoader</code> instance to make explicit API calls.
43
+ This would mostly be required for create/update/delete calls like POST, PUT, PATCH or DELETE</p>
44
+ {(data && data.length > 0) && <List items={data} />}
45
+ </div>);
46
+ };
47
+
48
+ export const RequestMiddleware = () => {
49
+ const [ data, setData ] = useState([]);
50
+ const { title } = data;
51
+
52
+ useEffect(() => {
53
+ dataLoader.addMiddleware("getTodo", {
54
+ requestParser: function(requestId, params) {
55
+ return {
56
+ todoId: params.id
57
+ };
58
+ }
59
+ });
60
+
61
+ const def = dataLoader.getRequestDef({
62
+ requestId: "getTodo",
63
+ params: {
64
+ id: 1
65
+ },
66
+ urlParams: {
67
+ todoId: 1
68
+ }
69
+ });
70
+
71
+ def.done((response) => {
72
+ setData(response);
73
+ });
74
+
75
+ def.catch((e) => {
76
+ console.error(e);
77
+ });
78
+ }, []);
79
+
80
+ return (<div>
81
+ <p>Use the <code>addMiddleware</code> functionality to add request middleware code to parse/modify the request data before sending it to the API.</p>
82
+ <div>Todo name is {title}</div>
83
+ </div>);
84
+ };
85
+
86
+ export const ResponseMiddleware = () => {
87
+ const [ data, setData ] = useState([]);
88
+ const { postName } = data;
89
+
90
+ useEffect(() => {
91
+ dataLoader.addMiddleware("getPost", {
92
+ responseParser: function(requestId, response) {
93
+ return {
94
+ postName: response.title
95
+ };
96
+ }
97
+ });
98
+
99
+ const def = dataLoader.getRequestDef({
100
+ requestId: "getPost",
101
+ urlParams: {
102
+ id: 1
103
+ }
104
+ });
105
+
106
+ def.done((response) => {
107
+ setData(response);
108
+ });
109
+
110
+ def.catch((e) => {
111
+ console.error(e);
112
+ });
113
+ }, []);
114
+
115
+ return (<div>
116
+ <p>Use the <code>addMiddleware</code> functionality to add response middleware code to parse/modify the response data before using it in the component</p>
117
+ <div>Post name is {postName}</div>
118
+ </div>);
119
+ };
120
+
121
+ export default {
122
+ title: "Data fetching|dataLoader (instance)"
123
+ };
@@ -0,0 +1,3 @@
1
+ export dataLoader from "./dataLoader";
2
+ export utils from "./utils";
3
+ export customHooks from "./customHooks";
@@ -0,0 +1,95 @@
1
+ import VALIDATORS from "./Validators";
2
+ let uniqueCounter = 1;
3
+
4
+ const utils = {
5
+ configs: {},
6
+ setDefaultConfigs: function(configs) {
7
+ this.configs = {...this.configs, ...configs};
8
+ },
9
+ getDefaultConfigs: function() {
10
+ return this.configs;
11
+ },
12
+ getDefaultConfig: function(key) {
13
+ return this.configs ? this.configs[key] : "";
14
+ },
15
+ getQueryParams: function(params = {}) {
16
+ let queryParams = [];
17
+
18
+ queryParams = Object.keys(params).map(key => {
19
+ return `${key}=${params[key]}`;
20
+ });
21
+
22
+ return queryParams.join("&");
23
+ },
24
+ isEven: function(value) {
25
+ return value % 2 === 0;
26
+ },
27
+ getPagIndex: function(pageConfig) {
28
+ const { perPageCount, pageNo } = pageConfig;
29
+ const startIndex = (pageNo - 1) * perPageCount;
30
+ const endIndex = pageNo * perPageCount;
31
+
32
+ return {
33
+ start: startIndex,
34
+ end: endIndex
35
+ };
36
+ },
37
+ omit: function(object = {}, omitKeys = []) {
38
+ let newObject = {};
39
+
40
+ for (let key in object) {
41
+ if (omitKeys.indexOf(key) === -1) {
42
+ newObject[key] = object[key];
43
+ }
44
+ }
45
+
46
+ return newObject;
47
+ },
48
+ getUniqueId: function() {
49
+ return uniqueCounter++;
50
+ },
51
+ isObjectEmpty: function(obj) {
52
+ return Object.keys(obj).length ? false : true;
53
+ },
54
+ debounce: function(func, debounceTime) {
55
+ let timeout;
56
+
57
+ return function() {
58
+ const context = this,
59
+ args = arguments;
60
+ clearTimeout(timeout);
61
+ timeout = setTimeout(function() {
62
+ timeout = null;
63
+ func.apply(context, args);
64
+ }, debounceTime);
65
+ };
66
+ },
67
+ checkIfValid: function(value, validations) {
68
+ let isValidValue = true;
69
+ let errorMessage;
70
+
71
+ for (let i = 0; i < validations.length; i++) {
72
+ const validationObj = validations[i];
73
+ const { type, message = "Invalid field value" } = validationObj;
74
+ isValidValue = VALIDATORS[type](value, validationObj);
75
+
76
+ if (!isValidValue) {
77
+ errorMessage = message;
78
+ break;
79
+ }
80
+ }
81
+
82
+ return {
83
+ isValid: isValidValue,
84
+ error: errorMessage
85
+ };
86
+ },
87
+ isObject: function(value) {
88
+ return Object.prototype.toString.call(value) === "[object Object]";
89
+ },
90
+ isArray: function(value) {
91
+ return Object.prototype.toString.call(value) === "[object Array]";
92
+ }
93
+ }
94
+
95
+ export default utils;
package/src/index.js ADDED
@@ -0,0 +1,68 @@
1
+ import {
2
+ Button,
3
+ DropdownButton,
4
+ List,
5
+ Modal,
6
+ InlineModal,
7
+ DataLoader,
8
+ Form,
9
+ Input,
10
+ Textarea,
11
+ Checkbox,
12
+ RadioList,
13
+ Dropdown,
14
+ RangeSlider,
15
+ FileUploader,
16
+ DragDropFileUploader,
17
+ Toggle,
18
+ Table,
19
+ PaginationComponent,
20
+ TabsComponent,
21
+ NotificationComponent,
22
+ ProgressBar,
23
+ Tooltip,
24
+ Accordian
25
+ } from "./components";
26
+
27
+ import {
28
+ dataLoader,
29
+ utils,
30
+ customHooks
31
+ } from "./core";
32
+
33
+ import { ButtonAppearance, ButtonSize } from "./components/Button";
34
+
35
+ import { InlineModalActivator, InlineModalBody } from "./components/InlineModal";
36
+
37
+ export {
38
+ Button,
39
+ ButtonAppearance,
40
+ ButtonSize,
41
+ DropdownButton,
42
+ List,
43
+ Modal,
44
+ InlineModal,
45
+ InlineModalActivator,
46
+ InlineModalBody,
47
+ Form,
48
+ Input,
49
+ Textarea,
50
+ Checkbox,
51
+ RadioList,
52
+ Dropdown,
53
+ RangeSlider,
54
+ FileUploader,
55
+ DragDropFileUploader,
56
+ Toggle,
57
+ DataLoader,
58
+ Table,
59
+ PaginationComponent,
60
+ TabsComponent,
61
+ NotificationComponent,
62
+ ProgressBar,
63
+ Tooltip,
64
+ Accordian,
65
+ dataLoader,
66
+ utils,
67
+ customHooks
68
+ };
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import { storiesOf } from "@storybook/react";
3
+ import #{component_name} from "./#{component_name}";
4
+
5
+ storiesOf("#{component_name}", module)
6
+ .add("Simple Usage", () => {
7
+ return (<#{component_name}></#{component_name}>);
8
+ });