@unbxd-ui/unbxd-react-components 0.2.104 → 0.2.107-beta.2

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 (289) hide show
  1. package/.babelrc +4 -0
  2. package/.eslintrc.js +38 -0
  3. package/CONTRIBUTE.md +105 -0
  4. package/components/Accordian/Accordian.js +45 -13
  5. package/components/Accordian/Accordian.stories.js +25 -6
  6. package/components/Accordian/index.js +3 -0
  7. package/components/Button/Button.js +26 -9
  8. package/components/Button/Button.stories.js +14 -1
  9. package/components/Button/DropdownButton.js +31 -9
  10. package/components/Button/DropdownButton.stories.js +23 -6
  11. package/components/Button/index.js +8 -1
  12. package/components/DataLoader/DataLoader.js +40 -10
  13. package/components/DataLoader/DataLoader.stories.js +30 -5
  14. package/components/DataLoader/index.js +3 -0
  15. package/components/Form/Checkbox.js +42 -14
  16. package/components/Form/DragDropFileUploader.js +42 -12
  17. package/components/Form/Dropdown.js +181 -104
  18. package/components/Form/FileUploader.js +32 -10
  19. package/components/Form/Form.js +45 -15
  20. package/components/Form/FormElementWrapper.js +7 -2
  21. package/components/Form/Input.js +72 -27
  22. package/components/Form/RadioList.js +48 -17
  23. package/components/Form/RangeSlider.js +73 -37
  24. package/components/Form/ServerPaginatedDDList.js +130 -87
  25. package/components/Form/Textarea.js +43 -18
  26. package/components/Form/Toggle.js +48 -16
  27. package/components/Form/index.js +30 -18
  28. package/components/Form/stories/Checkbox.stories.js +12 -1
  29. package/components/Form/stories/DragDropFileUploader.stories.js +8 -0
  30. package/components/Form/stories/Dropdown.stories.js +24 -6
  31. package/components/Form/stories/FileUploader.stories.js +8 -0
  32. package/components/Form/stories/FormDefault.stories.js +21 -1
  33. package/components/Form/stories/RadioList.stories.js +12 -1
  34. package/components/Form/stories/RangeSlider.stories.js +15 -1
  35. package/components/Form/stories/TextInput.stories.js +19 -3
  36. package/components/Form/stories/Textarea.stories.js +12 -1
  37. package/components/Form/stories/Toggle.stories.js +7 -0
  38. package/components/Form/stories/form.stories.js +40 -3
  39. package/components/InlineModal/InlineModal.js +51 -14
  40. package/components/InlineModal/InlineModal.stories.js +14 -2
  41. package/components/InlineModal/index.js +6 -1
  42. package/components/List/List.js +24 -9
  43. package/components/List/index.js +3 -0
  44. package/components/List/list.stories.js +10 -0
  45. package/components/Modal/Modal.js +49 -17
  46. package/components/Modal/Modal.stories.js +15 -1
  47. package/components/Modal/index.js +3 -0
  48. package/components/NotificationComponent/NotificationComponent.js +34 -11
  49. package/components/NotificationComponent/NotificationComponent.stories.js +6 -0
  50. package/components/NotificationComponent/index.js +3 -0
  51. package/components/ProgressBar/ProgressBar.js +11 -2
  52. package/components/ProgressBar/ProgressBar.stories.js +6 -0
  53. package/components/ProgressBar/index.js +3 -0
  54. package/components/Table/BaseTable.js +134 -69
  55. package/components/Table/PaginationComponent.js +23 -11
  56. package/components/Table/Table.js +149 -68
  57. package/components/Table/Table.stories.js +67 -22
  58. package/components/Table/index.js +4 -0
  59. package/components/TabsComponent/TabsComponent.js +57 -20
  60. package/components/TabsComponent/TabsComponent.stories.js +16 -0
  61. package/components/TabsComponent/index.js +3 -0
  62. package/components/Tooltip/Tooltip.js +47 -25
  63. package/components/Tooltip/Tooltip.stories.js +6 -0
  64. package/components/Tooltip/index.js +3 -0
  65. package/components/core.css +1 -3
  66. package/components/index.js +17 -1
  67. package/components/theme.css +0 -2
  68. package/lib/Readme.md +82 -0
  69. package/lib/components/Accordian/Accordian.js +117 -0
  70. package/lib/components/Accordian/Accordian.stories.js +137 -0
  71. package/lib/components/Accordian/index.js +10 -0
  72. package/lib/components/Button/Button.js +84 -0
  73. package/lib/components/Button/Button.stories.js +89 -0
  74. package/lib/components/Button/DropdownButton.js +77 -0
  75. package/lib/components/Button/DropdownButton.stories.js +51 -0
  76. package/lib/components/Button/index.js +32 -0
  77. package/lib/components/DataLoader/DataLoader.js +88 -0
  78. package/lib/components/DataLoader/DataLoader.stories.js +77 -0
  79. package/lib/components/DataLoader/index.js +10 -0
  80. package/lib/components/Form/Checkbox.js +93 -0
  81. package/lib/components/Form/DragDropFileUploader.js +85 -0
  82. package/lib/components/Form/Dropdown.js +478 -0
  83. package/lib/components/Form/FileUploader.js +81 -0
  84. package/lib/components/Form/Form.js +106 -0
  85. package/lib/components/Form/FormElementWrapper.js +27 -0
  86. package/lib/components/Form/Input.js +140 -0
  87. package/lib/components/Form/RadioList.js +111 -0
  88. package/lib/components/Form/RangeSlider.js +142 -0
  89. package/lib/components/Form/ServerPaginatedDDList.js +267 -0
  90. package/lib/components/Form/Textarea.js +95 -0
  91. package/lib/components/Form/Toggle.js +117 -0
  92. package/lib/components/Form/index.js +73 -0
  93. package/lib/components/Form/stories/Checkbox.stories.js +54 -0
  94. package/lib/components/Form/stories/DragDropFileUploader.stories.js +27 -0
  95. package/lib/components/Form/stories/Dropdown.stories.js +114 -0
  96. package/lib/components/Form/stories/FileUploader.stories.js +31 -0
  97. package/lib/components/Form/stories/FormDefault.stories.js +117 -0
  98. package/lib/components/Form/stories/RadioList.stories.js +55 -0
  99. package/lib/components/Form/stories/RangeSlider.stories.js +82 -0
  100. package/lib/components/Form/stories/TextInput.stories.js +79 -0
  101. package/lib/components/Form/stories/Textarea.stories.js +48 -0
  102. package/lib/components/Form/stories/Toggle.stories.js +25 -0
  103. package/lib/components/Form/stories/form.stories.js +240 -0
  104. package/lib/components/InlineModal/InlineModal.js +146 -0
  105. package/lib/components/InlineModal/InlineModal.stories.js +61 -0
  106. package/lib/components/InlineModal/index.js +24 -0
  107. package/lib/components/List/List.js +76 -0
  108. package/lib/components/List/index.js +10 -0
  109. package/lib/components/List/list.stories.js +38 -0
  110. package/lib/components/Modal/Modal.js +117 -0
  111. package/lib/components/Modal/Modal.stories.js +55 -0
  112. package/lib/components/Modal/index.js +10 -0
  113. package/lib/components/NotificationComponent/NotificationComponent.js +76 -0
  114. package/lib/components/NotificationComponent/NotificationComponent.stories.js +29 -0
  115. package/lib/components/NotificationComponent/index.js +10 -0
  116. package/lib/components/ProgressBar/ProgressBar.js +49 -0
  117. package/lib/components/ProgressBar/ProgressBar.stories.js +21 -0
  118. package/lib/components/ProgressBar/index.js +10 -0
  119. package/lib/components/Table/BaseTable.js +352 -0
  120. package/lib/components/Table/PaginationComponent.js +87 -0
  121. package/lib/components/Table/Table.js +333 -0
  122. package/lib/components/Table/Table.stories.js +204 -0
  123. package/lib/components/Table/index.js +17 -0
  124. package/lib/components/TabsComponent/TabsComponent.js +134 -0
  125. package/lib/components/TabsComponent/TabsComponent.stories.js +65 -0
  126. package/lib/components/TabsComponent/index.js +10 -0
  127. package/lib/components/Tooltip/Tooltip.js +102 -0
  128. package/lib/components/Tooltip/Tooltip.stories.js +25 -0
  129. package/lib/components/Tooltip/index.js +10 -0
  130. package/lib/components/core.css +3 -0
  131. package/lib/components/core.scss +29 -0
  132. package/lib/components/index.js +159 -0
  133. package/lib/components/theme.css +3 -0
  134. package/lib/components/theme.scss +11 -0
  135. package/lib/package-lock.json +20607 -0
  136. package/lib/package.json +94 -0
  137. package/package.json +1 -1
  138. package/src/Intro.stories.mdx +119 -0
  139. package/src/components/Accordian/Accordian.js +89 -0
  140. package/src/components/Accordian/Accordian.stories.js +92 -0
  141. package/src/components/Accordian/accordianCore.css +1 -0
  142. package/src/components/Accordian/accordianCore.scss +8 -0
  143. package/src/components/Accordian/accordianTheme.css +1 -0
  144. package/src/components/Accordian/accordianTheme.scss +6 -0
  145. package/src/components/Accordian/index.js +3 -0
  146. package/src/components/Button/Button.js +67 -0
  147. package/src/components/Button/Button.stories.js +103 -0
  148. package/src/components/Button/DropdownButton.js +60 -0
  149. package/src/components/Button/DropdownButton.stories.js +38 -0
  150. package/src/components/Button/button.css +1 -0
  151. package/src/components/Button/buttonTheme.css +1 -0
  152. package/src/components/Button/buttonTheme.scss +45 -0
  153. package/src/components/Button/index.js +5 -0
  154. package/src/components/DataLoader/DataLoader.js +86 -0
  155. package/src/components/DataLoader/DataLoader.stories.js +72 -0
  156. package/src/components/DataLoader/index.js +3 -0
  157. package/src/components/Form/Checkbox.js +73 -0
  158. package/src/components/Form/DragDropFileUploader.js +67 -0
  159. package/src/components/Form/Dropdown.js +430 -0
  160. package/src/components/Form/FileUploader.js +64 -0
  161. package/src/components/Form/Form.js +83 -0
  162. package/src/components/Form/FormElementWrapper.js +22 -0
  163. package/src/components/Form/Input.js +121 -0
  164. package/src/components/Form/RadioList.js +86 -0
  165. package/src/components/Form/RangeSlider.js +100 -0
  166. package/src/components/Form/ServerPaginatedDDList.js +231 -0
  167. package/src/components/Form/Textarea.js +76 -0
  168. package/src/components/Form/Toggle.js +96 -0
  169. package/src/components/Form/form.css +1 -0
  170. package/src/components/Form/formCore.css +1 -0
  171. package/src/components/Form/formCore.scss +142 -0
  172. package/src/components/Form/formTheme.css +1 -0
  173. package/src/components/Form/formTheme.scss +27 -0
  174. package/src/components/Form/index.js +13 -0
  175. package/src/components/Form/stories/Checkbox.stories.js +41 -0
  176. package/src/components/Form/stories/DragDropFileUploader.stories.js +21 -0
  177. package/src/components/Form/stories/Dropdown.stories.js +124 -0
  178. package/src/components/Form/stories/FileUploader.stories.js +21 -0
  179. package/src/components/Form/stories/FormDefault.stories.js +87 -0
  180. package/src/components/Form/stories/RadioList.stories.js +48 -0
  181. package/src/components/Form/stories/RangeSlider.stories.js +84 -0
  182. package/src/components/Form/stories/TextInput.stories.js +77 -0
  183. package/src/components/Form/stories/Textarea.stories.js +43 -0
  184. package/src/components/Form/stories/Toggle.stories.js +14 -0
  185. package/src/components/Form/stories/form.stories.js +216 -0
  186. package/src/components/InlineModal/InlineModal.js +135 -0
  187. package/src/components/InlineModal/InlineModal.stories.js +54 -0
  188. package/src/components/InlineModal/index.js +4 -0
  189. package/src/components/InlineModal/inlineModal.css +1 -0
  190. package/src/components/InlineModal/inlineModalCore.css +1 -0
  191. package/src/components/InlineModal/inlineModalCore.scss +31 -0
  192. package/src/components/InlineModal/inlineModalTheme.css +1 -0
  193. package/src/components/InlineModal/inlineModalTheme.scss +16 -0
  194. package/src/components/List/List.js +72 -0
  195. package/src/components/List/index.js +3 -0
  196. package/src/components/List/list.css +1 -0
  197. package/src/components/List/list.stories.js +28 -0
  198. package/src/components/List/listCore.css +1 -0
  199. package/src/components/List/listCore.scss +6 -0
  200. package/src/components/List/listTheme.css +0 -0
  201. package/src/components/List/listTheme.scss +0 -0
  202. package/src/components/Modal/Modal.js +99 -0
  203. package/src/components/Modal/Modal.stories.js +54 -0
  204. package/src/components/Modal/index.js +3 -0
  205. package/src/components/Modal/modal.css +1 -0
  206. package/src/components/Modal/modalCore.css +1 -0
  207. package/src/components/Modal/modalCore.scss +34 -0
  208. package/src/components/Modal/modalTheme.css +0 -0
  209. package/src/components/Modal/modalTheme.scss +0 -0
  210. package/src/components/NotificationComponent/NotificationComponent.js +58 -0
  211. package/src/components/NotificationComponent/NotificationComponent.stories.js +28 -0
  212. package/src/components/NotificationComponent/index.js +3 -0
  213. package/src/components/NotificationComponent/notificationComponent.css +1 -0
  214. package/src/components/NotificationComponent/notificationTheme.css +1 -0
  215. package/src/components/NotificationComponent/notificationTheme.scss +30 -0
  216. package/src/components/ProgressBar/ProgressBar.js +45 -0
  217. package/src/components/ProgressBar/ProgressBar.stories.js +14 -0
  218. package/src/components/ProgressBar/index.js +3 -0
  219. package/src/components/ProgressBar/progressBar.css +1 -0
  220. package/src/components/ProgressBar/progressBarCore.css +1 -0
  221. package/src/components/ProgressBar/progressBarCore.scss +14 -0
  222. package/src/components/ProgressBar/progressBarTheme.css +0 -0
  223. package/src/components/ProgressBar/progressBarTheme.scss +0 -0
  224. package/src/components/Table/BaseTable.js +306 -0
  225. package/src/components/Table/PaginationComponent.js +73 -0
  226. package/src/components/Table/Table.js +295 -0
  227. package/src/components/Table/Table.stories.js +198 -0
  228. package/src/components/Table/index.js +8 -0
  229. package/src/components/Table/table.css +1 -0
  230. package/src/components/Table/tableCore.css +1 -0
  231. package/src/components/Table/tableCore.scss +94 -0
  232. package/src/components/Table/tableTheme.css +1 -0
  233. package/src/components/Table/tableTheme.scss +34 -0
  234. package/src/components/TabsComponent/TabsComponent.js +99 -0
  235. package/src/components/TabsComponent/TabsComponent.stories.js +69 -0
  236. package/src/components/TabsComponent/index.js +3 -0
  237. package/src/components/TabsComponent/tabs.css +1 -0
  238. package/src/components/TabsComponent/tabsCore.css +1 -0
  239. package/src/components/TabsComponent/tabsCore.scss +59 -0
  240. package/src/components/TabsComponent/tabsTheme.css +0 -0
  241. package/src/components/TabsComponent/tabsTheme.scss +0 -0
  242. package/src/components/Tooltip/Tooltip.js +87 -0
  243. package/src/components/Tooltip/Tooltip.stories.js +16 -0
  244. package/src/components/Tooltip/index.js +3 -0
  245. package/src/components/Tooltip/tooltipCore.css +1 -0
  246. package/src/components/Tooltip/tooltipCore.scss +22 -0
  247. package/src/components/Tooltip/tooltipTheme.css +1 -0
  248. package/src/components/Tooltip/tooltipTheme.scss +21 -0
  249. package/src/components/core.css +1 -0
  250. package/src/components/core.scss +29 -0
  251. package/src/components/index.js +38 -0
  252. package/src/components/theme.css +1 -0
  253. package/src/components/theme.scss +11 -0
  254. package/src/core/Validators.js +34 -0
  255. package/src/core/customHooks.js +20 -0
  256. package/src/core/dataLoader.js +143 -0
  257. package/src/core/dataLoader.stories.js +123 -0
  258. package/src/core/index.js +3 -0
  259. package/src/core/utils.js +95 -0
  260. package/src/index.js +68 -0
  261. package/vscode-templates/NewStoryTemplate.stories.js +8 -0
  262. /package/{Readme.md → README.md} +0 -0
  263. /package/{components → lib/components}/Accordian/accordianCore.css +0 -0
  264. /package/{components → lib/components}/Accordian/accordianTheme.css +0 -0
  265. /package/{components → lib/components}/Button/buttonTheme.css +0 -0
  266. /package/{components → lib/components}/Form/formCore.css +0 -0
  267. /package/{components → lib/components}/Form/formTheme.css +0 -0
  268. /package/{components → lib/components}/InlineModal/inlineModalCore.css +0 -0
  269. /package/{components → lib/components}/InlineModal/inlineModalTheme.css +0 -0
  270. /package/{components → lib/components}/List/listCore.css +0 -0
  271. /package/{components → lib/components}/List/listTheme.css +0 -0
  272. /package/{components → lib/components}/Modal/modalCore.css +0 -0
  273. /package/{components → lib/components}/Modal/modalTheme.css +0 -0
  274. /package/{components → lib/components}/NotificationComponent/notificationTheme.css +0 -0
  275. /package/{components → lib/components}/ProgressBar/progressBarCore.css +0 -0
  276. /package/{components → lib/components}/ProgressBar/progressBarTheme.css +0 -0
  277. /package/{components → lib/components}/Table/tableCore.css +0 -0
  278. /package/{components → lib/components}/Table/tableTheme.css +0 -0
  279. /package/{components → lib/components}/TabsComponent/tabsCore.css +0 -0
  280. /package/{components → lib/components}/TabsComponent/tabsTheme.css +0 -0
  281. /package/{components → lib/components}/Tooltip/tooltipCore.css +0 -0
  282. /package/{components → lib/components}/Tooltip/tooltipTheme.css +0 -0
  283. /package/{core → lib/core}/Validators.js +0 -0
  284. /package/{core → lib/core}/customHooks.js +0 -0
  285. /package/{core → lib/core}/dataLoader.js +0 -0
  286. /package/{core → lib/core}/dataLoader.stories.js +0 -0
  287. /package/{core → lib/core}/index.js +0 -0
  288. /package/{core → lib/core}/utils.js +0 -0
  289. /package/{index.js → lib/index.js} +0 -0
@@ -0,0 +1,306 @@
1
+ import React, { Fragment, useEffect, useState, useImperativeHandle, forwardRef } from "react";
2
+ import PropTypes from "prop-types";
3
+ import utils from "../../core/utils";
4
+ import Checkbox from "../Form/Checkbox";
5
+
6
+ const DEFAULT_CHECKBOX_CONFIG = {
7
+ enabled: false,
8
+ showInHeader: true
9
+ };
10
+
11
+ const DefaultNoDataComponent = () => {
12
+ return (<div className="RCB-no-data">No data found</div>)
13
+ };
14
+
15
+ /* eslint-disable react/prop-types */
16
+
17
+ const getTDValue = ({ columnValue, rowData = {}, columnConfig = {}, tdProps = {}}) => {
18
+ const { key, valueFormatter, ColumnComponent, componentProps = {} } = columnConfig;
19
+ let tdValue = columnValue;
20
+
21
+ if (typeof(valueFormatter) === "function") {
22
+ tdValue = valueFormatter({value: columnValue, record: rowData});
23
+ } else if (ColumnComponent) {
24
+ tdValue = <ColumnComponent record={rowData} {...componentProps} />
25
+ }
26
+
27
+ return <td key={key} {...tdProps}>{tdValue}</td>
28
+ }
29
+
30
+ const ExpandableTR = (props) => {
31
+ const {
32
+ rowIndex,
33
+ rowData,
34
+ columnConfigs,
35
+ isEven,
36
+ ExpandedRowComponent,
37
+ showCheckbox,
38
+ checkboxChangeCounter,
39
+ checkboxValue,
40
+ onSelectionChange
41
+ } = props;
42
+ const [ selected, setSelected ] = useState(checkboxValue || false);
43
+ const [ isExpanded, setIsExpanded ] = useState(false);
44
+
45
+ const onChange = (value) => {
46
+ setSelected(value);
47
+ onSelectionChange(rowData, value);
48
+ };
49
+
50
+ useEffect(() => {
51
+ setSelected(checkboxValue);
52
+ }, [checkboxChangeCounter, checkboxValue]);
53
+
54
+ const toggleExpanded = () => {
55
+ setIsExpanded(!isExpanded);
56
+ };
57
+
58
+ const className = "RCB-tr RCB-parent-row " + (isEven ? "RCB-even-tr" : "RCB-odd-tr");
59
+
60
+ return (<Fragment>
61
+ <tr className={className}>
62
+ {/* add column for expand toggle icon */}
63
+ {getTDValue({
64
+ columnValue: "",
65
+ columnConfig: {
66
+ key: "expandIcon"
67
+ },
68
+ tdProps: {
69
+ onClick: toggleExpanded,
70
+ className: isExpanded ? "expand-open" : "expand-close"
71
+ }
72
+ })}
73
+ {showCheckbox && <td key={`checkbox-colum-${rowIndex}`}>
74
+ <Checkbox name={`checkbox${rowIndex}`} type="checkbox" className="table-checkbox" onChange={onChange} value={selected} />
75
+ </td>}
76
+ {columnConfigs.map(configObj => {
77
+ const { key } = configObj;
78
+ return getTDValue({
79
+ columnValue: rowData[key],
80
+ rowData,
81
+ columnConfig: configObj,
82
+ tdProps: {
83
+ onClick: toggleExpanded
84
+ }
85
+ });
86
+ })}
87
+ </tr>
88
+ {isExpanded && <tr className="RCB-expanded-row">
89
+ {/* +1 is to accomodate the expand toggle icon column */}
90
+ <td colSpan={columnConfigs.length + 1}>
91
+ <ExpandedRowComponent parentRecord={rowData} />
92
+ </td>
93
+ </tr>}
94
+ </Fragment>);
95
+ };
96
+
97
+ ExpandableTR.propTypes = {
98
+ ExpandedRowComponent: PropTypes.any.isRequired // TODO : check for a React Component
99
+ };
100
+
101
+ const TR = (props) => {
102
+ const {
103
+ rowIndex,
104
+ rowData,
105
+ columnConfigs,
106
+ isEven,
107
+ showCheckbox,
108
+ checkboxChangeCounter,
109
+ checkboxValue,
110
+ onSelectionChange } = props;
111
+ const [ selected, setSelected ] = useState(checkboxValue || false);
112
+ const className = "RCB-tr " + (isEven ? "RCB-even-tr" : "RCB-odd-tr");
113
+
114
+ const onChange = (value) => {
115
+ setSelected(value);
116
+ onSelectionChange(rowData, value);
117
+ };
118
+
119
+ useEffect(() => {
120
+ setSelected(checkboxValue);
121
+ }, [checkboxChangeCounter, checkboxValue]);
122
+
123
+ return (<tr className={className}>
124
+ {showCheckbox && <td key={`checkbox-colum-${rowIndex}`}>
125
+ <Checkbox name={`checkbox${rowIndex}`} type="checkbox" className="table-checkbox" onChange={onChange} value={selected} />
126
+ </td>}
127
+ {columnConfigs.map(configObj => {
128
+ const { key } = configObj;
129
+ return getTDValue({columnValue: rowData[key], rowData, columnConfig: configObj});
130
+ })}
131
+ </tr>);
132
+ };
133
+
134
+ let BaseTable = (props, ref) => {
135
+ const {
136
+ className,
137
+ records,
138
+ columnConfigs,
139
+ idAttribute,
140
+ checkboxConfig,
141
+ isExpandableTable,
142
+ ExpandedRowComponent,
143
+ noDataComponent,
144
+ sortByConfig,
145
+ resetPageNo
146
+ } = props;
147
+ const { enabled:showCheckbox, showInHeader } = {...DEFAULT_CHECKBOX_CONFIG, ...(checkboxConfig || {})};
148
+ const { sortBy, sortOrder } = sortByConfig;
149
+
150
+ const [ checkboxValue, setCheckboxValue ] = useState(false);
151
+ const [ checkboxChangeCounter, setChangeCounter ] = useState(0);
152
+ const [ selected, setSelected ] = useState([]);
153
+
154
+ const RowComponent = isExpandableTable ? ExpandableTR : TR;
155
+
156
+ const onSelectionChange = (record, checked) => {
157
+ if (checked) {
158
+ /* add to selected array */
159
+ setSelected([...selected, record]);
160
+ } else {
161
+ /* remove from selected array */
162
+ const newSelected = selected.filter(obj => {
163
+ return obj[idAttribute] !== record[idAttribute];
164
+ });
165
+
166
+ setSelected(newSelected);
167
+ }
168
+ };
169
+
170
+ const getSelectedRows = () => {
171
+ return selected;
172
+ };
173
+
174
+ const updateCheckboxValue = (newValue) => {
175
+ setCheckboxValue(newValue);
176
+ setChangeCounter(checkboxChangeCounter + 1);
177
+ };
178
+
179
+ const resetSelected = () => {
180
+ updateCheckboxValue(false);
181
+ setSelected([]);
182
+ };
183
+
184
+ const toggleSelectAll = () => {
185
+ const checked = !checkboxValue;
186
+ updateCheckboxValue(checked);
187
+
188
+ if (checked) {
189
+ setSelected(records);
190
+ } else {
191
+ setSelected([]);
192
+ }
193
+ };
194
+
195
+ useImperativeHandle(ref, () => ({
196
+ getSelectedRows,
197
+ resetSelected,
198
+ resetPageNo
199
+ }));
200
+
201
+ if (records.length === 0) {
202
+ return noDataComponent;
203
+ } else {
204
+ return (<table className={`RCB-table ${className}`}>
205
+ <thead>
206
+ <tr>
207
+ {/* add empty column for expand icon */}
208
+ {isExpandableTable && <th key="expandIcon" className="RCB-th RCB-expand-column"></th>}
209
+ {showCheckbox && (showInHeader ? <th key="headerCheckbox">
210
+ <Checkbox name="headerCheckbox" type="checkbox" className="table-checkbox"
211
+ value={checkboxValue} onChange={toggleSelectAll} />
212
+ </th> : <th/>)}
213
+ {columnConfigs.map(columnObj => {
214
+ const { key, label, sortable, headerClassName } = columnObj;
215
+ let className = "RCB-th";
216
+ let thAttrs = {};
217
+
218
+ if (sortable) {
219
+ className += " RCB-th-sortable";
220
+
221
+ if (sortBy === key) {
222
+ className += ` RCB-th-${sortOrder.toLowerCase()}`;
223
+ } else {
224
+ className += " RCB-th-sort";
225
+ }
226
+
227
+ thAttrs = {
228
+ onClick: () => {
229
+ props.onSort(columnObj);
230
+ }
231
+ }
232
+ }
233
+
234
+ if (headerClassName) {
235
+ className += ` ${headerClassName}`;
236
+ }
237
+
238
+ return (<th className={className} key={key} {...thAttrs}>{label}</th>);
239
+ })}
240
+ </tr>
241
+ </thead>
242
+ <tbody>
243
+ {records.map((rowData, index)=> {
244
+ return <RowComponent key={rowData[idAttribute]}
245
+ isEven={utils.isEven(index)} rowIndex={index}
246
+ rowData={rowData}
247
+ columnConfigs={columnConfigs}
248
+ ExpandedRowComponent={ExpandedRowComponent}
249
+ showCheckbox={showCheckbox} checkboxValue={checkboxValue} checkboxChangeCounter={checkboxChangeCounter}
250
+ onSelectionChange={onSelectionChange} />
251
+ })}
252
+ </tbody>
253
+ </table>)
254
+ }
255
+ };
256
+
257
+ BaseTable = forwardRef(BaseTable);
258
+
259
+ /* eslint-enable react/prop-types */
260
+
261
+ BaseTable.propTypes = {
262
+ /** Pass any additional classNames to Table component */
263
+ className: PropTypes.string,
264
+ /** Array containing table row data */
265
+ records: function(props, propName) {
266
+ if (props["paginationType"] == "CLIENT") {
267
+ if (!props[propName]) {
268
+ return new Error("Please provide the table records for paginationType 'CLIENT'!");
269
+ }
270
+
271
+ if (Object.prototype.toString.call(props[propName]) !== "[object Array]") {
272
+ return new Error("'records' must be an array");
273
+ }
274
+ }
275
+ },
276
+ /** Array containing the table columns config */
277
+ columnConfigs: PropTypes.array.isRequired,
278
+ /** ID attribute key to use when rendering the dropdown items */
279
+ idAttribute: PropTypes.string,
280
+ /* Config to display checkbox in the first column of the table
281
+ * {
282
+ enabled: false, // turn this on to display checkbox in first column of the table
283
+ showInHeader: true // turn this off to not display the checkbox in the table header
284
+ }
285
+ */
286
+ checkboxConfig: PropTypes.object,
287
+ /** set to "true" if table rows are expandable */
288
+ isExpandableTable: PropTypes.bool,
289
+ /** Component to be rendered on expanding a row */
290
+ ExpandedRowComponent: PropTypes.oneOfType([
291
+ PropTypes.instanceOf(Element),
292
+ PropTypes.func
293
+ ]),
294
+ /** Component to be rendered if the table has no data */
295
+ noDataComponent: PropTypes.any
296
+ }
297
+
298
+ BaseTable.defaultProps = {
299
+ className: "",
300
+ records: [],
301
+ idAttribute: "id",
302
+ isExpandableTable: false,
303
+ noDataComponent: <DefaultNoDataComponent />
304
+ };
305
+
306
+ export default BaseTable;
@@ -0,0 +1,73 @@
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import Dropdown from "../Form/Dropdown";
4
+ import utils from "../../core/utils";
5
+
6
+ const PaginationComponent = (props) => {
7
+ const {
8
+ pageSizeList,
9
+ pageConfig,
10
+ onPageConfigChanged
11
+ } = props;
12
+
13
+ const { perPageCount, pageNo, total } = pageConfig;
14
+
15
+ const SelectionSummary = () => {
16
+ const pagIndex = utils.getPagIndex(pageConfig);
17
+ const { start, end } = pagIndex;
18
+ const startVal = start + 1;
19
+ const endVal = total < end ? total : end;
20
+ const summaryString = `${startVal}-${endVal}`;
21
+
22
+ return (<div className="RCB-select-summary">{summaryString}<span className="RCB-select-arrow"></span></div>);
23
+ };
24
+
25
+ const onPerPageChanged = (perPageObj) => {
26
+ const perPage = +(perPageObj.id);
27
+ onPageConfigChanged({
28
+ ...pageConfig,
29
+ pageNo: 1,
30
+ perPageCount: perPage,
31
+ });
32
+ };
33
+
34
+ const changePage = (moveUnit, event) => {
35
+ event.preventDefault();
36
+ onPageConfigChanged({
37
+ ...pageConfig,
38
+ pageNo: pageNo + moveUnit
39
+ });
40
+ };
41
+
42
+ let isLeftNavDisbaled = (pageNo <= 1);
43
+ let isRightNavDisbaled = (pageNo >= Math.ceil(total / +perPageCount));
44
+
45
+ return (<div className="RCB-paginate-wrapper">
46
+ <Dropdown name="perPageCount"
47
+ showLabel={false} className="RCB-per-page-count"
48
+ options={pageSizeList}
49
+ onChange={onPerPageChanged}
50
+ SelectionSummary={SelectionSummary} />{`of ${total}`}
51
+ <div className="RCB-paginate-nav">
52
+ <a href="javacsript:void(0)" className={`RCB-page-nav ${isLeftNavDisbaled ? "disabled" : ""}`}
53
+ onClick={(event) => changePage(-1,event)}>
54
+ {"<"}
55
+ </a>
56
+ <a href="javacsript:void(0)" className={`RCB-page-nav ${isRightNavDisbaled ? "disabled" : ""}`}
57
+ onClick={(event) => changePage(1,event)}>
58
+ {">"}
59
+ </a>
60
+ </div>
61
+ </div>);
62
+ };
63
+
64
+ PaginationComponent.propTypes = {
65
+ pageSizeList: PropTypes.arrayOf(PropTypes.shape({
66
+ id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
67
+ name: PropTypes.string
68
+ })),
69
+ pageConfig: PropTypes.object,
70
+ onPageConfigChanged: PropTypes.func.isRequired
71
+ };
72
+
73
+ export default PaginationComponent;
@@ -0,0 +1,295 @@
1
+ import React, { useState, useEffect, useImperativeHandle } from "react";
2
+ import PropTypes from "prop-types";
3
+ import BaseTable from "./BaseTable";
4
+ import DataLoader from "../DataLoader";
5
+ import PaginationComponent from "./PaginationComponent";
6
+ import utils from "../../core/utils";
7
+ import { forwardRef } from "react";
8
+
9
+ const getPageRecords = (records = [], pageConfig = {}) => {
10
+ const pagIndex = utils.getPagIndex(pageConfig);
11
+ const { start, end } = pagIndex;
12
+
13
+ return records.slice(start, end);
14
+ };
15
+
16
+ const sortNumbersASC = (a, b) => a - b;
17
+ const sortNumbersDSC = (a, b) => b - a;
18
+ const sortAlphaASC = (a, b) => a < b ? -1 : 1;
19
+ const sortAlphaDSC = (a, b) => b < a ? -1 : 1;
20
+
21
+ const getFilteredRecords = ({records = [], searchBy, searchByKey, sortByConfig}) => {
22
+ let filteredRecords = records;
23
+
24
+ if (searchBy) {
25
+ searchBy = searchBy.toLowerCase();
26
+
27
+ filteredRecords = records.filter(obj => {
28
+ const val = (obj[searchByKey] ? obj[searchByKey] : "").toLowerCase();
29
+ return (val.indexOf(searchBy) !== -1)
30
+ });
31
+ }
32
+
33
+ if (typeof(sortByConfig) === "object" && !utils.isObjectEmpty(sortByConfig)) {
34
+ const { sortBy, sortOrder, columnConfig } = sortByConfig;
35
+ const { valueFormatter } = columnConfig;
36
+
37
+ filteredRecords = records.slice().sort((obj1, obj2) =>{
38
+ let rowValue1 = obj1[sortBy];
39
+ let rowValue2 = obj2[sortBy];
40
+
41
+ const sortValue1 = typeof(valueFormatter) === "function" ?
42
+ valueFormatter({value: rowValue1, record: obj1}) : rowValue1;
43
+ const sortValue2 = typeof(valueFormatter) === "function" ?
44
+ valueFormatter({value: rowValue2, record: obj2}) : rowValue2;
45
+
46
+ if (typeof(sortValue) === "number") {
47
+ return sortOrder === "ASC" ? sortNumbersASC(sortValue1, sortValue2) : sortNumbersDSC(sortValue1, sortValue2);
48
+ } else {
49
+ return sortOrder === "ASC" ? sortAlphaASC(sortValue1, sortValue2) : sortAlphaDSC(sortValue1, sortValue2);
50
+ }
51
+ });
52
+ }
53
+
54
+ return filteredRecords;
55
+ };
56
+
57
+ export const REQUEST_KEYS = {
58
+ searchBy: "search",
59
+ sortBy: "sortBy",
60
+ sortOrder: "sortOrder",
61
+ sortASC: "ASC",
62
+ sortDSC: "DSC"
63
+ };
64
+
65
+ let Table = (props, ref) => {
66
+ const {
67
+ className,
68
+ wrapperClassName,
69
+ records,
70
+ columnConfigs,
71
+ idAttribute,
72
+ searchBy,
73
+ getRequestKeys,
74
+ showPaginateBar,
75
+ paginationPosition,
76
+ paginationType,
77
+ paginationBar,
78
+ requestId,
79
+ pageNoKey,
80
+ perPageKey,
81
+ pageSizeList,
82
+ isExpandableTable,
83
+ ExpandedRowComponent,
84
+ responseFormatter,
85
+ noDataComponent,
86
+ omitProps,
87
+ getUrlParams,
88
+ getRequestParams,
89
+ checkboxConfig,
90
+ ...restProps
91
+ } = props;
92
+ /* variables for server data */
93
+ const [ serverRecords, setServerRecords ] = useState([]);
94
+ const [ serverTotal, setServerTotal ] = useState(0);
95
+
96
+ /* variables for search, sort data */
97
+ const [ searchQuery, setSearchQuery ] = useState(searchBy);
98
+ const [ sortByConfig, setSortByConfig ] = useState({});
99
+ const { sortBy, sortOrder } = sortByConfig;
100
+
101
+ /* variables for pagination data */
102
+ const [ pageConfig, setPageConfig ] = useState({
103
+ perPageCount: pageSizeList[0].id,
104
+ pageNo: 1
105
+ });
106
+ const { perPageCount, pageNo } = pageConfig;
107
+ const omitParams = [pageNoKey, perPageKey, ...omitProps.split(",")]
108
+
109
+ let {
110
+ searchBy:searchByKey,
111
+ sortBy:sortByKey,
112
+ sortOrder:sortOrderKey,
113
+ sortASC:ASCEnum,
114
+ sortDSC:DSCEnum
115
+ } = {...REQUEST_KEYS, ...getRequestKeys()};
116
+
117
+ let extraParams = utils.omit(restProps, omitParams);
118
+ let requestParams = {
119
+ ...getRequestParams(),
120
+ ...extraParams,
121
+ [pageNoKey]: pageNo,
122
+ [perPageKey]: perPageCount,
123
+ ...(searchQuery && {[searchByKey]: searchQuery}),
124
+ ...(sortBy && {[sortByKey]: sortBy}),
125
+ ...(sortOrder && {[sortOrderKey]: sortOrder === "DSC" ? DSCEnum : ASCEnum})
126
+ };
127
+
128
+ const requests = [{
129
+ requestId: requestId,
130
+ params: requestParams,
131
+ urlParams: getUrlParams()
132
+ }];
133
+
134
+ const onDataLoaded = ([response]) => {
135
+ let apiResponse = response;
136
+
137
+ if (typeof(responseFormatter) === "function") {
138
+ apiResponse = responseFormatter(response);
139
+ }
140
+
141
+ let { entries, total } = apiResponse;
142
+ entries = entries || [];
143
+
144
+ if (pageNo > 1 && entries.length === 0) {
145
+ /* current page does not have records, so fetch previous page */
146
+ setPageConfig({
147
+ ...pageConfig,
148
+ pageNo: pageNo - 1
149
+ });
150
+ }
151
+
152
+ setServerRecords(entries);
153
+ setServerTotal(total);
154
+ };
155
+
156
+ const resetPageNo = () => {
157
+ setPageConfig({
158
+ ...pageConfig,
159
+ pageNo: 1
160
+ });
161
+ };
162
+
163
+ useEffect(() => {
164
+ /* Search value changed: reset pageNo. */
165
+ resetPageNo();
166
+ setSearchQuery(searchBy);
167
+ }, [searchBy]);
168
+
169
+ const onSort = (columnConfig) => {
170
+ const newSortBy = columnConfig.key;
171
+ let newSortOrder = "ASC";
172
+
173
+ if (sortBy === newSortBy) {
174
+ /* clicked sort on the same column */
175
+ newSortOrder = sortOrder === "ASC" ? "DSC" : "ASC";
176
+ }
177
+
178
+ setSortByConfig({
179
+ sortBy: newSortBy,
180
+ sortOrder: newSortOrder,
181
+ columnConfig
182
+ });
183
+ };
184
+
185
+ const filteredRecords = getFilteredRecords({records, searchBy, searchByKey, sortByConfig});
186
+ const totalRecords = paginationType === "SERVER" ? serverTotal : filteredRecords.length;
187
+ const paginationProps = {
188
+ pageSizeList: pageSizeList,
189
+ onPageConfigChanged: setPageConfig,
190
+ pageConfig: {...pageConfig, total: totalRecords}
191
+ };
192
+
193
+ const paginationComponent = (<div className="RCB-paginate-bar">
194
+ {paginationBar ? React.cloneElement(paginationBar, paginationProps)
195
+ : <PaginationComponent {...paginationProps}/>}
196
+ </div>);
197
+
198
+ let finalRecords = paginationType === "SERVER" ? serverRecords :
199
+ (showPaginateBar ? getPageRecords(filteredRecords, pageConfig) : filteredRecords);
200
+
201
+ let wrappedComponent = (<BaseTable ref={ref} records={finalRecords} columnConfigs={columnConfigs} checkboxConfig={checkboxConfig}
202
+ idAttribute={idAttribute} noDataComponent={noDataComponent}
203
+ sortByConfig={sortByConfig} onSort={onSort} resetPageNo={resetPageNo}
204
+ isExpandableTable={isExpandableTable} ExpandedRowComponent={ExpandedRowComponent} />);
205
+
206
+ if (paginationType === "SERVER") {
207
+ wrappedComponent = (<DataLoader requests={requests} onDataLoaded={onDataLoaded}>
208
+ {wrappedComponent}
209
+ </DataLoader>)
210
+ }
211
+
212
+ return (
213
+ <div className={className}>
214
+ {showPaginateBar && paginationPosition === "TOP" && totalRecords > 0 && paginationComponent}
215
+ <div className={wrapperClassName}>
216
+ {wrappedComponent}
217
+ </div>
218
+ {showPaginateBar && paginationPosition === "BOTTOM" && totalRecords > 0 && paginationComponent}
219
+ </div>
220
+ )
221
+ };
222
+
223
+ Table = forwardRef(Table);
224
+
225
+ Table.propTypes = {
226
+ /** Extends Table properties */
227
+ ...BaseTable.propTypes,
228
+ /** search value to search data in the table */
229
+ searchBy: PropTypes.string,
230
+ /** list of supported page sizes */
231
+ pageSizeList: PropTypes.array,
232
+ /** set to false to disable pagination bar */
233
+ showPaginateBar: PropTypes.bool,
234
+ /** location where the pagination component must be displayed */
235
+ paginationPosition: PropTypes.oneOf(["TOP", "BOTTOM"]),
236
+ /** CLIENT side pagination or SERVER side pagination */
237
+ paginationType: PropTypes.oneOf(["CLIENT", "SERVER"]),
238
+ /** You can provide a custom component for the pagination bar
239
+ * if you want to add more content to the pagination bar other than the pagination widget.
240
+ * Make sure to include <PagniationComponent /> and pass on all the props sent to this custom component
241
+ */
242
+ paginationBar: PropTypes.any,
243
+ /** [SERVER side pagination] the ID of the request to call */
244
+ requestId: PropTypes.string,
245
+ /** [SERVER side pagination] key to send the page number value in, to the API */
246
+ pageNoKey: PropTypes.string,
247
+ /** [SERVER side pagination] key to send the page count value in, to the API */
248
+ perPageKey: PropTypes.string,
249
+ /** If paginationType is "SERVER",
250
+ * component expects the response to be of the form
251
+ * { [pageNoKey]: <pageNo>, [perPageKey]: <pageSize>, total: <totalCount>, entries: [{}] }
252
+ * If your data is not in this format, use the responseFormatter to format the data to this structure.
253
+ * Input to this function is the response received from your API
254
+ * */
255
+ responseFormatter: PropTypes.func,
256
+ /** If paginationType is "SERVER",
257
+ * a comma separated list of the props to be omitted from being added to the API request */
258
+ omitProps: PropTypes.string,
259
+ /** If paginationType is "SERVER", function that is expected to return the key configs for the various request settings
260
+ * in the format { searchBy, sortBy, sortOrder }
261
+ */
262
+ getRequestKeys: PropTypes.func,
263
+ /** If paginationType is "SERVER", function that is expected to return the URL Params object */
264
+ getUrlParams: PropTypes.func,
265
+ /** If paginationType is "SERVER", function that is expected to return the Request Params object */
266
+ getRequestParams: PropTypes.func
267
+ }
268
+
269
+ Table.defaultProps = {
270
+ ...BaseTable.defaultProps,
271
+ pageSizeList: [{
272
+ id: "10",
273
+ name: "10"
274
+ }, {
275
+ id: "20",
276
+ name: "20"
277
+ }, {
278
+ id: "50",
279
+ name: "50"
280
+ }, {
281
+ id: "100",
282
+ name: "100"
283
+ }],
284
+ showPaginateBar: true,
285
+ paginationPosition: "TOP",
286
+ paginationType: "CLIENT",
287
+ pageNoKey: "page",
288
+ perPageKey: "count",
289
+ omitProps: "",
290
+ getRequestKeys: () => ({}),
291
+ getUrlParams: () => ({}),
292
+ getRequestParams: () => ({})
293
+ };
294
+
295
+ export default Table;