jattac.libs.web.responsive-table 0.1.6 → 0.2.0

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.
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  var React = require('react');
4
6
 
5
7
  function styleInject(css, ref) {
@@ -29,14 +31,947 @@ function styleInject(css, ref) {
29
31
  }
30
32
  }
31
33
 
32
- var css_248z = "/* Using CSS variables for a more maintainable and themeable design */\n:root {\n --table-border-color: #e0e0e0;\n --table-header-bg: #f8f9fa;\n --table-row-hover-bg: #e9ecef;\n --table-row-stripe-bg: #f2f2f2;\n --card-bg: #ffffff;\n --card-border-color: #e0e0e0;\n --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n --text-color: #212529;\n --text-color-muted: #6c757d;\n --interactive-color: #0056b3;\n}\n\n/* Mobile Card View */\n.ResponsiveTable-module_card__b-U2v {\n background-color: var(--card-bg);\n border: 1px solid var(--card-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: var(--card-shadow);\n transition: box-shadow 0.2s ease-in-out;\n}\n\n.ResponsiveTable-module_card__b-U2v:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n/* This is not used in the component, but keeping it styled in case it's added back */\n.ResponsiveTable-module_card-header__Ttk51 {\n background-color: var(--table-header-bg);\n padding: 0.75rem 1rem;\n font-weight: 600; /* Bolder */\n border-bottom: 1px solid var(--table-border-color);\n}\n\n.ResponsiveTable-module_card-body__XIy0h {\n padding: 1rem;\n font-size: 0.9rem;\n}\n\n.ResponsiveTable-module_card-body__XIy0h p {\n margin: 0 0 0.75rem;\n display: flex;\n justify-content: space-between;\n}\n\n.ResponsiveTable-module_card-body__XIy0h p:last-child {\n margin-bottom: 0;\n}\n\n.ResponsiveTable-module_card-label__v9L71 {\n font-weight: 600;\n color: var(--text-color);\n margin-right: 0.5rem;\n}\n\n/* Desktop Table View */\n.ResponsiveTable-module_responsiveTable__4y-Od {\n width: 100%;\n border-collapse: collapse;\n color: var(--text-color);\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od thead th {\n background-color: var(--table-header-bg);\n position: sticky;\n top: 0;\n z-index: 2;\n font-weight: 600;\n text-align: left;\n padding: 1rem;\n border-bottom: 2px solid var(--table-border-color);\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od td {\n padding: 1rem;\n border-bottom: 1px solid var(--table-border-color);\n text-align: left;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od tr {\n background-color: var(--card-bg);\n transition: background-color 0.2s ease-in-out;\n}\n\n/* Subtle striping for better readability */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(even) {\n background-color: var(--table-row-stripe-bg);\n}\n\n/* Modern hover effect */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:hover {\n background-color: var(--table-row-hover-bg);\n}\n\n/* Clickable Header Style */\n.ResponsiveTable-module_clickableHeader__xHQhF {\n cursor: pointer;\n color: var(--interactive-color);\n}\n\n.ResponsiveTable-module_clickableHeader__xHQhF:hover {\n text-decoration: underline;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od tfoot {\n background-color: var(--table-header-bg);\n border-top: 2px solid var(--table-border-color);\n font-weight: 600;\n}\n\n.ResponsiveTable-module_footerCell__8H-uG {\n padding: 1rem;\n text-align: right;\n font-weight: 600;\n}\n\n.ResponsiveTable-module_clickableFooterCell__WB9Ss {\n cursor: pointer;\n color: var(--interactive-color);\n}\n\n.ResponsiveTable-module_clickableFooterCell__WB9Ss:hover {\n text-decoration: underline;\n}\n\n.ResponsiveTable-module_footerCard__-NE2M {\n background-color: var(--table-header-bg);\n border: 1px solid var(--card-border-color);\n border-top: 2px solid var(--table-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: none;\n}\n\n.ResponsiveTable-module_footer-card-body__CtBMv {\n padding: 1rem;\n font-size: 0.9rem;\n}\n\n.ResponsiveTable-module_footer-card-row__Vv6Ur {\n margin: 0 0 0.75rem;\n display: flex;\n justify-content: space-between;\n font-weight: 600;\n}\n\n/* No Data State */\n\n/* Staggered Entrance Animation */\n.ResponsiveTable-module_animatedRow__SFjrJ {\n animation: ResponsiveTable-module_fadeInUp__jMCS7 0.5s ease-out forwards;\n opacity: 0;\n}\n\n@keyframes ResponsiveTable-module_fadeInUp__jMCS7 {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Skeleton Loader */\n.ResponsiveTable-module_skeleton__XxsXW {\n background-color: #e0e0e0;\n border-radius: 4px;\n position: relative;\n overflow: hidden;\n}\n\n.ResponsiveTable-module_skeleton__XxsXW::after {\n content: '';\n position: absolute;\n top: 0;\n left: -150%;\n width: 150%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);\n animation: ResponsiveTable-module_shimmer__H8PhC 1.5s infinite;\n}\n\n.ResponsiveTable-module_skeletonText__T-Lgq {\n height: 1.2em;\n width: 100%;\n}\n\n.ResponsiveTable-module_skeletonCard__AYVwL {\n background-color: var(--card-bg);\n border: 1px solid var(--card-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n padding: 1rem;\n}\n\n@keyframes ResponsiveTable-module_shimmer__H8PhC {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(100%);\n }\n}\n.ResponsiveTable-module_noDataWrapper__Rj-k3 {\n color: var(--text-color-muted); /* Softer color */\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n gap: 10px;\n padding: 40px;\n background-color: var(--table-header-bg);\n border: 1px dashed var(--table-border-color);\n border-radius: 8px;\n}\n\n.ResponsiveTable-module_noData__IpwNq {\n text-align: center;\n font-weight: 500; /* Less aggressive than bold */\n font-size: 1rem;\n}\n";
34
+ var css_248z = "/* Using CSS variables for a more maintainable and themeable design */\n:root {\n --table-border-color: #e0e0e0;\n --table-header-bg: #f8f9fa;\n --table-row-hover-bg: #e9ecef;\n --table-row-stripe-bg: #f2f2f2;\n --card-bg: #ffffff;\n --card-border-color: #e0e0e0;\n --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n --text-color: #212529;\n --text-color-muted: #6c757d;\n --interactive-color: #0056b3;\n}\n\n/* Mobile Card View */\n.ResponsiveTable-module_card__b-U2v {\n background-color: var(--card-bg);\n border: 1px solid var(--card-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: var(--card-shadow);\n transition: box-shadow 0.2s ease-in-out;\n}\n\n.ResponsiveTable-module_card__b-U2v:hover {\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n}\n\n/* This is not used in the component, but keeping it styled in case it's added back */\n.ResponsiveTable-module_card-header__Ttk51 {\n background-color: var(--table-header-bg);\n padding: 0.75rem 1rem;\n font-weight: 600; /* Bolder */\n border-bottom: 1px solid var(--table-border-color);\n}\n\n.ResponsiveTable-module_card-body__XIy0h {\n padding: 1rem;\n font-size: 0.9rem;\n}\n\n.ResponsiveTable-module_card-body__XIy0h p {\n margin: 0 0 0.75rem;\n display: flex;\n justify-content: space-between;\n}\n\n.ResponsiveTable-module_card-body__XIy0h p:last-child {\n margin-bottom: 0;\n}\n\n.ResponsiveTable-module_card-label__v9L71 {\n font-weight: 600;\n color: var(--text-color);\n margin-right: 0.5rem;\n}\n\n/* Desktop Table View */\n.ResponsiveTable-module_responsiveTable__4y-Od {\n width: 100%;\n border-collapse: collapse;\n color: var(--text-color);\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od thead th {\n background-color: var(--table-header-bg);\n position: sticky;\n top: 0;\n z-index: 2;\n font-weight: 600;\n text-align: left;\n padding: 1rem;\n border-bottom: 2px solid var(--table-border-color);\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od td {\n padding: 1rem;\n border-bottom: 1px solid var(--table-border-color);\n text-align: left;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od tr {\n background-color: var(--card-bg);\n transition: background-color 0.2s ease-in-out;\n}\n\n/* Subtle striping for better readability */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:nth-child(even) {\n background-color: var(--table-row-stripe-bg);\n}\n\n/* Modern hover effect */\n.ResponsiveTable-module_responsiveTable__4y-Od tr:hover {\n background-color: var(--table-row-hover-bg);\n}\n\n/* Clickable Header Style */\n.ResponsiveTable-module_clickableHeader__xHQhF {\n cursor: pointer;\n color: var(--interactive-color);\n}\n\n.ResponsiveTable-module_clickableHeader__xHQhF:hover {\n text-decoration: underline;\n}\n\n.ResponsiveTable-module_responsiveTable__4y-Od tfoot {\n background-color: var(--table-header-bg);\n border-top: 2px solid var(--table-border-color);\n font-weight: 600;\n}\n\n.ResponsiveTable-module_footerCell__8H-uG {\n padding: 1rem;\n text-align: right;\n font-weight: 600;\n}\n\n.ResponsiveTable-module_clickableFooterCell__WB9Ss {\n cursor: pointer;\n color: var(--interactive-color);\n}\n\n.ResponsiveTable-module_clickableFooterCell__WB9Ss:hover {\n text-decoration: underline;\n}\n\n.ResponsiveTable-module_footerCard__-NE2M {\n background-color: var(--table-header-bg);\n border: 1px solid var(--card-border-color);\n border-top: 2px solid var(--table-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n box-shadow: none;\n}\n\n.ResponsiveTable-module_footer-card-body__CtBMv {\n padding: 1rem;\n font-size: 0.9rem;\n}\n\n.ResponsiveTable-module_footer-card-row__Vv6Ur {\n margin: 0 0 0.75rem;\n display: flex;\n justify-content: space-between;\n font-weight: 600;\n}\n\n/* No Data State */\n\n/* Staggered Entrance Animation */\n.ResponsiveTable-module_animatedRow__SFjrJ {\n animation: ResponsiveTable-module_fadeInUp__jMCS7 0.5s ease-out forwards;\n opacity: 0;\n}\n\n@keyframes ResponsiveTable-module_fadeInUp__jMCS7 {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Skeleton Loader */\n.ResponsiveTable-module_skeleton__XxsXW {\n background-color: #e0e0e0;\n border-radius: 4px;\n position: relative;\n overflow: hidden;\n}\n\n.ResponsiveTable-module_skeleton__XxsXW::after {\n content: '';\n position: absolute;\n top: 0;\n left: -150%;\n width: 150%;\n height: 100%;\n background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);\n animation: ResponsiveTable-module_shimmer__H8PhC 1.5s infinite;\n}\n\n.ResponsiveTable-module_skeletonText__T-Lgq {\n height: 1.2em;\n width: 100%;\n}\n\n.ResponsiveTable-module_skeletonCard__AYVwL {\n background-color: var(--card-bg);\n border: 1px solid var(--card-border-color);\n margin-bottom: 1rem;\n border-radius: 8px;\n overflow: hidden;\n padding: 1rem;\n}\n\n@keyframes ResponsiveTable-module_shimmer__H8PhC {\n 0% {\n transform: translateX(0);\n }\n 100% {\n transform: translateX(100%);\n }\n}\n.ResponsiveTable-module_noDataWrapper__Rj-k3 {\n color: var(--text-color-muted); /* Softer color */\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n gap: 10px;\n padding: 40px;\n background-color: var(--table-header-bg);\n border: 1px dashed var(--table-border-color);\n border-radius: 8px;\n}\n\n.ResponsiveTable-module_noData__IpwNq {\n text-align: center;\n font-weight: 500; /* Less aggressive than bold */\n font-size: 1rem;\n}\n\n.ResponsiveTable-module_row-exit__EVX6T {\n opacity: 0;\n transform: scaleY(0);\n transition: transform 0.3s ease-out, opacity 0.3s ease-out;\n}\n\n.ResponsiveTable-module_row-enter__YKgI4 {\n opacity: 0;\n transform: translateY(20px);\n transition: transform 0.5s ease-out, opacity 0.5s ease-out;\n}\n\n.ResponsiveTable-module_row-flash__a4NOm {\n animation: ResponsiveTable-module_flash__nxeAX 0.5s ease-out;\n}\n\n@keyframes ResponsiveTable-module_flash__nxeAX {\n 0% {\n background-color: var(--table-row-hover-bg);\n }\n 100% {\n background-color: transparent;\n }\n}\n";
33
35
  var styles = {"card":"ResponsiveTable-module_card__b-U2v","card-header":"ResponsiveTable-module_card-header__Ttk51","card-body":"ResponsiveTable-module_card-body__XIy0h","card-label":"ResponsiveTable-module_card-label__v9L71","responsiveTable":"ResponsiveTable-module_responsiveTable__4y-Od","clickableHeader":"ResponsiveTable-module_clickableHeader__xHQhF","footerCell":"ResponsiveTable-module_footerCell__8H-uG","clickableFooterCell":"ResponsiveTable-module_clickableFooterCell__WB9Ss","footerCard":"ResponsiveTable-module_footerCard__-NE2M","footer-card-body":"ResponsiveTable-module_footer-card-body__CtBMv","footer-card-row":"ResponsiveTable-module_footer-card-row__Vv6Ur","animatedRow":"ResponsiveTable-module_animatedRow__SFjrJ","skeleton":"ResponsiveTable-module_skeleton__XxsXW","skeletonText":"ResponsiveTable-module_skeletonText__T-Lgq","skeletonCard":"ResponsiveTable-module_skeletonCard__AYVwL","noDataWrapper":"ResponsiveTable-module_noDataWrapper__Rj-k3","noData":"ResponsiveTable-module_noData__IpwNq"};
34
36
  styleInject(css_248z);
35
37
 
38
+ class FilterPlugin {
39
+ constructor() {
40
+ this.id = 'filter';
41
+ this.filterText = '';
42
+ this.onPluginInit = (api) => {
43
+ this.api = api;
44
+ };
45
+ this.renderHeader = () => {
46
+ var _a;
47
+ if (!((_a = this.api.filterProps) === null || _a === void 0 ? void 0 : _a.showFilter)) {
48
+ return null;
49
+ }
50
+ return (React.createElement("div", { style: { float: 'right', marginBottom: '1rem' } },
51
+ React.createElement("input", { type: "text", placeholder: this.api.filterProps.filterPlaceholder || "Search...", onChange: this.handleFilterChange, style: {
52
+ padding: '0.5rem',
53
+ border: '1px solid #ccc',
54
+ borderRadius: '4px',
55
+ } })));
56
+ };
57
+ this.processData = (data) => {
58
+ if (!this.filterText || !this.api.columnDefinitions) {
59
+ return data;
60
+ }
61
+ const lowercasedFilter = this.filterText.toLowerCase();
62
+ return data.filter((row) => {
63
+ return this.api.columnDefinitions.some((colDef) => {
64
+ // If colDef is a function, it won't have getFilterableValue, so skip it.
65
+ if (typeof colDef === 'function') {
66
+ return false;
67
+ }
68
+ // Now we know colDef is an object (IResponsiveTableColumnDefinition<TData>)
69
+ const typedColDef = colDef;
70
+ // Check if getFilterableValue exists and is a function
71
+ if (typedColDef.getFilterableValue && typeof typedColDef.getFilterableValue === 'function') {
72
+ const value = typedColDef.getFilterableValue(row);
73
+ return value === null || value === void 0 ? void 0 : value.toString().toLowerCase().includes(lowercasedFilter);
74
+ }
75
+ return false; // If getFilterableValue is not present or not a function
76
+ });
77
+ });
78
+ };
79
+ this.handleFilterChange = (e) => {
80
+ // Debounce the filter change
81
+ setTimeout(() => {
82
+ this.filterText = e.target.value;
83
+ this.api.forceUpdate();
84
+ }, 300);
85
+ };
86
+ }
87
+ }
88
+
89
+ /******************************************************************************
90
+ Copyright (c) Microsoft Corporation.
91
+
92
+ Permission to use, copy, modify, and/or distribute this software for any
93
+ purpose with or without fee is hereby granted.
94
+
95
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
96
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
97
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
98
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
99
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
100
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
101
+ PERFORMANCE OF THIS SOFTWARE.
102
+ ***************************************************************************** */
103
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
104
+
105
+
106
+ function __awaiter(thisArg, _arguments, P, generator) {
107
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
108
+ return new (P || (P = Promise))(function (resolve, reject) {
109
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
110
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
111
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
112
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
113
+ });
114
+ }
115
+
116
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
117
+ var e = new Error(message);
118
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
119
+ };
120
+
121
+ class InfiniteScrollPlugin {
122
+ constructor() {
123
+ this.id = 'infinite-scroll';
124
+ this.isLoadingMore = false;
125
+ this.onPluginInit = (api) => {
126
+ this.api = api;
127
+ this.attachScrollListener();
128
+ };
129
+ this.attachScrollListener = () => {
130
+ var _a, _b;
131
+ const scrollableElement = (_b = (_a = this.api).getScrollableElement) === null || _b === void 0 ? void 0 : _b.call(_a);
132
+ if (scrollableElement) {
133
+ scrollableElement.addEventListener('scroll', this.handleScroll);
134
+ }
135
+ };
136
+ this.handleScroll = () => __awaiter(this, void 0, void 0, function* () {
137
+ var _a, _b, _c, _d, _e;
138
+ const scrollableElement = (_b = (_a = this.api).getScrollableElement) === null || _b === void 0 ? void 0 : _b.call(_a);
139
+ if (!scrollableElement || !((_c = this.api.infiniteScrollProps) === null || _c === void 0 ? void 0 : _c.enableInfiniteScroll)) {
140
+ return;
141
+ }
142
+ const { scrollTop, scrollHeight, clientHeight } = scrollableElement;
143
+ const scrollThreshold = 200; // Load more data when 200px from the bottom
144
+ if (scrollHeight - scrollTop - clientHeight < scrollThreshold &&
145
+ this.api.infiniteScrollProps.hasMore &&
146
+ !this.isLoadingMore) {
147
+ this.isLoadingMore = true;
148
+ this.api.forceUpdate(); // Trigger re-render to show loading component
149
+ yield ((_e = (_d = this.api.infiniteScrollProps).onLoadMore) === null || _e === void 0 ? void 0 : _e.call(_d, this.api.getData()));
150
+ this.isLoadingMore = false;
151
+ this.api.forceUpdate(); // Trigger re-render to hide loading component
152
+ }
153
+ });
154
+ this.processData = (data) => {
155
+ // This plugin doesn't modify the data directly, but rather triggers loading more.
156
+ // The main component's data prop should be updated by the consumer of the table.
157
+ return data;
158
+ };
159
+ this.renderFooter = () => {
160
+ if (!this.api.infiniteScrollProps) {
161
+ return null;
162
+ }
163
+ if (this.isLoadingMore) {
164
+ return this.api.infiniteScrollProps.loadingMoreComponent || React.createElement("div", null, "Loading more...");
165
+ }
166
+ else if (!this.api.infiniteScrollProps.hasMore) {
167
+ return this.api.infiniteScrollProps.noMoreDataComponent || React.createElement("div", null, "No more data.");
168
+ }
169
+ return null;
170
+ };
171
+ }
172
+ }
173
+
174
+ function _extends() {
175
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
176
+ for (var e = 1; e < arguments.length; e++) {
177
+ var t = arguments[e];
178
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
179
+ }
180
+ return n;
181
+ }, _extends.apply(null, arguments);
182
+ }
183
+
184
+ function _assertThisInitialized(e) {
185
+ if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
186
+ return e;
187
+ }
188
+
189
+ function _setPrototypeOf(t, e) {
190
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
191
+ return t.__proto__ = e, t;
192
+ }, _setPrototypeOf(t, e);
193
+ }
194
+
195
+ function _inheritsLoose(t, o) {
196
+ t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o);
197
+ }
198
+
199
+ var safeIsNaN = Number.isNaN ||
200
+ function ponyfill(value) {
201
+ return typeof value === 'number' && value !== value;
202
+ };
203
+ function isEqual(first, second) {
204
+ if (first === second) {
205
+ return true;
206
+ }
207
+ if (safeIsNaN(first) && safeIsNaN(second)) {
208
+ return true;
209
+ }
210
+ return false;
211
+ }
212
+ function areInputsEqual(newInputs, lastInputs) {
213
+ if (newInputs.length !== lastInputs.length) {
214
+ return false;
215
+ }
216
+ for (var i = 0; i < newInputs.length; i++) {
217
+ if (!isEqual(newInputs[i], lastInputs[i])) {
218
+ return false;
219
+ }
220
+ }
221
+ return true;
222
+ }
223
+
224
+ function memoizeOne(resultFn, isEqual) {
225
+ if (isEqual === void 0) { isEqual = areInputsEqual; }
226
+ var lastThis;
227
+ var lastArgs = [];
228
+ var lastResult;
229
+ var calledOnce = false;
230
+ function memoized() {
231
+ var newArgs = [];
232
+ for (var _i = 0; _i < arguments.length; _i++) {
233
+ newArgs[_i] = arguments[_i];
234
+ }
235
+ if (calledOnce && lastThis === this && isEqual(newArgs, lastArgs)) {
236
+ return lastResult;
237
+ }
238
+ lastResult = resultFn.apply(this, newArgs);
239
+ calledOnce = true;
240
+ lastThis = this;
241
+ lastArgs = newArgs;
242
+ return lastResult;
243
+ }
244
+ return memoized;
245
+ }
246
+
247
+ // Animation frame based implementation of setTimeout.
248
+ // Inspired by Joe Lambert, https://gist.github.com/joelambert/1002116#file-requesttimeout-js
249
+ var hasNativePerformanceNow = typeof performance === 'object' && typeof performance.now === 'function';
250
+ var now = hasNativePerformanceNow ? function () {
251
+ return performance.now();
252
+ } : function () {
253
+ return Date.now();
254
+ };
255
+ function cancelTimeout(timeoutID) {
256
+ cancelAnimationFrame(timeoutID.id);
257
+ }
258
+ function requestTimeout(callback, delay) {
259
+ var start = now();
260
+
261
+ function tick() {
262
+ if (now() - start >= delay) {
263
+ callback.call(null);
264
+ } else {
265
+ timeoutID.id = requestAnimationFrame(tick);
266
+ }
267
+ }
268
+
269
+ var timeoutID = {
270
+ id: requestAnimationFrame(tick)
271
+ };
272
+ return timeoutID;
273
+ }
274
+
275
+ var size = -1; // This utility copied from "dom-helpers" package.
276
+
277
+ function getScrollbarSize(recalculate) {
278
+ if (recalculate === void 0) {
279
+ recalculate = false;
280
+ }
281
+
282
+ if (size === -1 || recalculate) {
283
+ var div = document.createElement('div');
284
+ var style = div.style;
285
+ style.width = '50px';
286
+ style.height = '50px';
287
+ style.overflow = 'scroll';
288
+ document.body.appendChild(div);
289
+ size = div.offsetWidth - div.clientWidth;
290
+ document.body.removeChild(div);
291
+ }
292
+
293
+ return size;
294
+ }
295
+ var cachedRTLResult = null; // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
296
+ // Chrome does not seem to adhere; its scrollLeft values are positive (measured relative to the left).
297
+ // Safari's elastic bounce makes detecting this even more complicated wrt potential false positives.
298
+ // The safest way to check this is to intentionally set a negative offset,
299
+ // and then verify that the subsequent "scroll" event matches the negative offset.
300
+ // If it does not match, then we can assume a non-standard RTL scroll implementation.
301
+
302
+ function getRTLOffsetType(recalculate) {
303
+ if (recalculate === void 0) {
304
+ recalculate = false;
305
+ }
306
+
307
+ if (cachedRTLResult === null || recalculate) {
308
+ var outerDiv = document.createElement('div');
309
+ var outerStyle = outerDiv.style;
310
+ outerStyle.width = '50px';
311
+ outerStyle.height = '50px';
312
+ outerStyle.overflow = 'scroll';
313
+ outerStyle.direction = 'rtl';
314
+ var innerDiv = document.createElement('div');
315
+ var innerStyle = innerDiv.style;
316
+ innerStyle.width = '100px';
317
+ innerStyle.height = '100px';
318
+ outerDiv.appendChild(innerDiv);
319
+ document.body.appendChild(outerDiv);
320
+
321
+ if (outerDiv.scrollLeft > 0) {
322
+ cachedRTLResult = 'positive-descending';
323
+ } else {
324
+ outerDiv.scrollLeft = 1;
325
+
326
+ if (outerDiv.scrollLeft === 0) {
327
+ cachedRTLResult = 'negative';
328
+ } else {
329
+ cachedRTLResult = 'positive-ascending';
330
+ }
331
+ }
332
+
333
+ document.body.removeChild(outerDiv);
334
+ return cachedRTLResult;
335
+ }
336
+
337
+ return cachedRTLResult;
338
+ }
339
+
340
+ if (process.env.NODE_ENV !== 'production') ;
341
+
342
+ var IS_SCROLLING_DEBOUNCE_INTERVAL$1 = 150;
343
+
344
+ var defaultItemKey$1 = function defaultItemKey(index, data) {
345
+ return index;
346
+ }; // In DEV mode, this Set helps us only log a warning once per component instance.
347
+ // This avoids spamming the console every time a render happens.
348
+
349
+
350
+ var devWarningsDirection = null;
351
+ var devWarningsTagName$1 = null;
352
+
353
+ if (process.env.NODE_ENV !== 'production') {
354
+ if (typeof window !== 'undefined' && typeof window.WeakSet !== 'undefined') {
355
+ devWarningsDirection = /*#__PURE__*/new WeakSet();
356
+ devWarningsTagName$1 = /*#__PURE__*/new WeakSet();
357
+ }
358
+ }
359
+
360
+ function createListComponent(_ref) {
361
+ var _class;
362
+
363
+ var getItemOffset = _ref.getItemOffset,
364
+ getEstimatedTotalSize = _ref.getEstimatedTotalSize,
365
+ getItemSize = _ref.getItemSize,
366
+ getOffsetForIndexAndAlignment = _ref.getOffsetForIndexAndAlignment,
367
+ getStartIndexForOffset = _ref.getStartIndexForOffset,
368
+ getStopIndexForStartIndex = _ref.getStopIndexForStartIndex,
369
+ initInstanceProps = _ref.initInstanceProps,
370
+ shouldResetStyleCacheOnItemSizeChange = _ref.shouldResetStyleCacheOnItemSizeChange,
371
+ validateProps = _ref.validateProps;
372
+ return _class = /*#__PURE__*/function (_PureComponent) {
373
+ _inheritsLoose(List, _PureComponent);
374
+
375
+ // Always use explicit constructor for React components.
376
+ // It produces less code after transpilation. (#26)
377
+ // eslint-disable-next-line no-useless-constructor
378
+ function List(props) {
379
+ var _this;
380
+
381
+ _this = _PureComponent.call(this, props) || this;
382
+ _this._instanceProps = initInstanceProps(_this.props, _assertThisInitialized(_this));
383
+ _this._outerRef = void 0;
384
+ _this._resetIsScrollingTimeoutId = null;
385
+ _this.state = {
386
+ instance: _assertThisInitialized(_this),
387
+ isScrolling: false,
388
+ scrollDirection: 'forward',
389
+ scrollOffset: typeof _this.props.initialScrollOffset === 'number' ? _this.props.initialScrollOffset : 0,
390
+ scrollUpdateWasRequested: false
391
+ };
392
+ _this._callOnItemsRendered = void 0;
393
+ _this._callOnItemsRendered = memoizeOne(function (overscanStartIndex, overscanStopIndex, visibleStartIndex, visibleStopIndex) {
394
+ return _this.props.onItemsRendered({
395
+ overscanStartIndex: overscanStartIndex,
396
+ overscanStopIndex: overscanStopIndex,
397
+ visibleStartIndex: visibleStartIndex,
398
+ visibleStopIndex: visibleStopIndex
399
+ });
400
+ });
401
+ _this._callOnScroll = void 0;
402
+ _this._callOnScroll = memoizeOne(function (scrollDirection, scrollOffset, scrollUpdateWasRequested) {
403
+ return _this.props.onScroll({
404
+ scrollDirection: scrollDirection,
405
+ scrollOffset: scrollOffset,
406
+ scrollUpdateWasRequested: scrollUpdateWasRequested
407
+ });
408
+ });
409
+ _this._getItemStyle = void 0;
410
+
411
+ _this._getItemStyle = function (index) {
412
+ var _this$props = _this.props,
413
+ direction = _this$props.direction,
414
+ itemSize = _this$props.itemSize,
415
+ layout = _this$props.layout;
416
+
417
+ var itemStyleCache = _this._getItemStyleCache(shouldResetStyleCacheOnItemSizeChange && itemSize, shouldResetStyleCacheOnItemSizeChange && layout, shouldResetStyleCacheOnItemSizeChange && direction);
418
+
419
+ var style;
420
+
421
+ if (itemStyleCache.hasOwnProperty(index)) {
422
+ style = itemStyleCache[index];
423
+ } else {
424
+ var _offset = getItemOffset(_this.props, index, _this._instanceProps);
425
+
426
+ var size = getItemSize(_this.props, index, _this._instanceProps); // TODO Deprecate direction "horizontal"
427
+
428
+ var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
429
+ var isRtl = direction === 'rtl';
430
+ var offsetHorizontal = isHorizontal ? _offset : 0;
431
+ itemStyleCache[index] = style = {
432
+ position: 'absolute',
433
+ left: isRtl ? undefined : offsetHorizontal,
434
+ right: isRtl ? offsetHorizontal : undefined,
435
+ top: !isHorizontal ? _offset : 0,
436
+ height: !isHorizontal ? size : '100%',
437
+ width: isHorizontal ? size : '100%'
438
+ };
439
+ }
440
+
441
+ return style;
442
+ };
443
+
444
+ _this._getItemStyleCache = void 0;
445
+ _this._getItemStyleCache = memoizeOne(function (_, __, ___) {
446
+ return {};
447
+ });
448
+
449
+ _this._onScrollHorizontal = function (event) {
450
+ var _event$currentTarget = event.currentTarget,
451
+ clientWidth = _event$currentTarget.clientWidth,
452
+ scrollLeft = _event$currentTarget.scrollLeft,
453
+ scrollWidth = _event$currentTarget.scrollWidth;
454
+
455
+ _this.setState(function (prevState) {
456
+ if (prevState.scrollOffset === scrollLeft) {
457
+ // Scroll position may have been updated by cDM/cDU,
458
+ // In which case we don't need to trigger another render,
459
+ // And we don't want to update state.isScrolling.
460
+ return null;
461
+ }
462
+
463
+ var direction = _this.props.direction;
464
+ var scrollOffset = scrollLeft;
465
+
466
+ if (direction === 'rtl') {
467
+ // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
468
+ // This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
469
+ // It's also easier for this component if we convert offsets to the same format as they would be in for ltr.
470
+ // So the simplest solution is to determine which browser behavior we're dealing with, and convert based on it.
471
+ switch (getRTLOffsetType()) {
472
+ case 'negative':
473
+ scrollOffset = -scrollLeft;
474
+ break;
475
+
476
+ case 'positive-descending':
477
+ scrollOffset = scrollWidth - clientWidth - scrollLeft;
478
+ break;
479
+ }
480
+ } // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
481
+
482
+
483
+ scrollOffset = Math.max(0, Math.min(scrollOffset, scrollWidth - clientWidth));
484
+ return {
485
+ isScrolling: true,
486
+ scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
487
+ scrollOffset: scrollOffset,
488
+ scrollUpdateWasRequested: false
489
+ };
490
+ }, _this._resetIsScrollingDebounced);
491
+ };
492
+
493
+ _this._onScrollVertical = function (event) {
494
+ var _event$currentTarget2 = event.currentTarget,
495
+ clientHeight = _event$currentTarget2.clientHeight,
496
+ scrollHeight = _event$currentTarget2.scrollHeight,
497
+ scrollTop = _event$currentTarget2.scrollTop;
498
+
499
+ _this.setState(function (prevState) {
500
+ if (prevState.scrollOffset === scrollTop) {
501
+ // Scroll position may have been updated by cDM/cDU,
502
+ // In which case we don't need to trigger another render,
503
+ // And we don't want to update state.isScrolling.
504
+ return null;
505
+ } // Prevent Safari's elastic scrolling from causing visual shaking when scrolling past bounds.
506
+
507
+
508
+ var scrollOffset = Math.max(0, Math.min(scrollTop, scrollHeight - clientHeight));
509
+ return {
510
+ isScrolling: true,
511
+ scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
512
+ scrollOffset: scrollOffset,
513
+ scrollUpdateWasRequested: false
514
+ };
515
+ }, _this._resetIsScrollingDebounced);
516
+ };
517
+
518
+ _this._outerRefSetter = function (ref) {
519
+ var outerRef = _this.props.outerRef;
520
+ _this._outerRef = ref;
521
+
522
+ if (typeof outerRef === 'function') {
523
+ outerRef(ref);
524
+ } else if (outerRef != null && typeof outerRef === 'object' && outerRef.hasOwnProperty('current')) {
525
+ outerRef.current = ref;
526
+ }
527
+ };
528
+
529
+ _this._resetIsScrollingDebounced = function () {
530
+ if (_this._resetIsScrollingTimeoutId !== null) {
531
+ cancelTimeout(_this._resetIsScrollingTimeoutId);
532
+ }
533
+
534
+ _this._resetIsScrollingTimeoutId = requestTimeout(_this._resetIsScrolling, IS_SCROLLING_DEBOUNCE_INTERVAL$1);
535
+ };
536
+
537
+ _this._resetIsScrolling = function () {
538
+ _this._resetIsScrollingTimeoutId = null;
539
+
540
+ _this.setState({
541
+ isScrolling: false
542
+ }, function () {
543
+ // Clear style cache after state update has been committed.
544
+ // This way we don't break pure sCU for items that don't use isScrolling param.
545
+ _this._getItemStyleCache(-1, null);
546
+ });
547
+ };
548
+
549
+ return _this;
550
+ }
551
+
552
+ List.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
553
+ validateSharedProps$1(nextProps, prevState);
554
+ validateProps(nextProps);
555
+ return null;
556
+ };
557
+
558
+ var _proto = List.prototype;
559
+
560
+ _proto.scrollTo = function scrollTo(scrollOffset) {
561
+ scrollOffset = Math.max(0, scrollOffset);
562
+ this.setState(function (prevState) {
563
+ if (prevState.scrollOffset === scrollOffset) {
564
+ return null;
565
+ }
566
+
567
+ return {
568
+ scrollDirection: prevState.scrollOffset < scrollOffset ? 'forward' : 'backward',
569
+ scrollOffset: scrollOffset,
570
+ scrollUpdateWasRequested: true
571
+ };
572
+ }, this._resetIsScrollingDebounced);
573
+ };
574
+
575
+ _proto.scrollToItem = function scrollToItem(index, align) {
576
+ if (align === void 0) {
577
+ align = 'auto';
578
+ }
579
+
580
+ var _this$props2 = this.props,
581
+ itemCount = _this$props2.itemCount,
582
+ layout = _this$props2.layout;
583
+ var scrollOffset = this.state.scrollOffset;
584
+ index = Math.max(0, Math.min(index, itemCount - 1)); // The scrollbar size should be considered when scrolling an item into view, to ensure it's fully visible.
585
+ // But we only need to account for its size when it's actually visible.
586
+ // This is an edge case for lists; normally they only scroll in the dominant direction.
587
+
588
+ var scrollbarSize = 0;
589
+
590
+ if (this._outerRef) {
591
+ var outerRef = this._outerRef;
592
+
593
+ if (layout === 'vertical') {
594
+ scrollbarSize = outerRef.scrollWidth > outerRef.clientWidth ? getScrollbarSize() : 0;
595
+ } else {
596
+ scrollbarSize = outerRef.scrollHeight > outerRef.clientHeight ? getScrollbarSize() : 0;
597
+ }
598
+ }
599
+
600
+ this.scrollTo(getOffsetForIndexAndAlignment(this.props, index, align, scrollOffset, this._instanceProps, scrollbarSize));
601
+ };
602
+
603
+ _proto.componentDidMount = function componentDidMount() {
604
+ var _this$props3 = this.props,
605
+ direction = _this$props3.direction,
606
+ initialScrollOffset = _this$props3.initialScrollOffset,
607
+ layout = _this$props3.layout;
608
+
609
+ if (typeof initialScrollOffset === 'number' && this._outerRef != null) {
610
+ var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
611
+
612
+ if (direction === 'horizontal' || layout === 'horizontal') {
613
+ outerRef.scrollLeft = initialScrollOffset;
614
+ } else {
615
+ outerRef.scrollTop = initialScrollOffset;
616
+ }
617
+ }
618
+
619
+ this._callPropsCallbacks();
620
+ };
621
+
622
+ _proto.componentDidUpdate = function componentDidUpdate() {
623
+ var _this$props4 = this.props,
624
+ direction = _this$props4.direction,
625
+ layout = _this$props4.layout;
626
+ var _this$state = this.state,
627
+ scrollOffset = _this$state.scrollOffset,
628
+ scrollUpdateWasRequested = _this$state.scrollUpdateWasRequested;
629
+
630
+ if (scrollUpdateWasRequested && this._outerRef != null) {
631
+ var outerRef = this._outerRef; // TODO Deprecate direction "horizontal"
632
+
633
+ if (direction === 'horizontal' || layout === 'horizontal') {
634
+ if (direction === 'rtl') {
635
+ // TRICKY According to the spec, scrollLeft should be negative for RTL aligned elements.
636
+ // This is not the case for all browsers though (e.g. Chrome reports values as positive, measured relative to the left).
637
+ // So we need to determine which browser behavior we're dealing with, and mimic it.
638
+ switch (getRTLOffsetType()) {
639
+ case 'negative':
640
+ outerRef.scrollLeft = -scrollOffset;
641
+ break;
642
+
643
+ case 'positive-ascending':
644
+ outerRef.scrollLeft = scrollOffset;
645
+ break;
646
+
647
+ default:
648
+ var clientWidth = outerRef.clientWidth,
649
+ scrollWidth = outerRef.scrollWidth;
650
+ outerRef.scrollLeft = scrollWidth - clientWidth - scrollOffset;
651
+ break;
652
+ }
653
+ } else {
654
+ outerRef.scrollLeft = scrollOffset;
655
+ }
656
+ } else {
657
+ outerRef.scrollTop = scrollOffset;
658
+ }
659
+ }
660
+
661
+ this._callPropsCallbacks();
662
+ };
663
+
664
+ _proto.componentWillUnmount = function componentWillUnmount() {
665
+ if (this._resetIsScrollingTimeoutId !== null) {
666
+ cancelTimeout(this._resetIsScrollingTimeoutId);
667
+ }
668
+ };
669
+
670
+ _proto.render = function render() {
671
+ var _this$props5 = this.props,
672
+ children = _this$props5.children,
673
+ className = _this$props5.className,
674
+ direction = _this$props5.direction,
675
+ height = _this$props5.height,
676
+ innerRef = _this$props5.innerRef,
677
+ innerElementType = _this$props5.innerElementType,
678
+ innerTagName = _this$props5.innerTagName,
679
+ itemCount = _this$props5.itemCount,
680
+ itemData = _this$props5.itemData,
681
+ _this$props5$itemKey = _this$props5.itemKey,
682
+ itemKey = _this$props5$itemKey === void 0 ? defaultItemKey$1 : _this$props5$itemKey,
683
+ layout = _this$props5.layout,
684
+ outerElementType = _this$props5.outerElementType,
685
+ outerTagName = _this$props5.outerTagName,
686
+ style = _this$props5.style,
687
+ useIsScrolling = _this$props5.useIsScrolling,
688
+ width = _this$props5.width;
689
+ var isScrolling = this.state.isScrolling; // TODO Deprecate direction "horizontal"
690
+
691
+ var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
692
+ var onScroll = isHorizontal ? this._onScrollHorizontal : this._onScrollVertical;
693
+
694
+ var _this$_getRangeToRend = this._getRangeToRender(),
695
+ startIndex = _this$_getRangeToRend[0],
696
+ stopIndex = _this$_getRangeToRend[1];
697
+
698
+ var items = [];
699
+
700
+ if (itemCount > 0) {
701
+ for (var _index = startIndex; _index <= stopIndex; _index++) {
702
+ items.push(React.createElement(children, {
703
+ data: itemData,
704
+ key: itemKey(_index, itemData),
705
+ index: _index,
706
+ isScrolling: useIsScrolling ? isScrolling : undefined,
707
+ style: this._getItemStyle(_index)
708
+ }));
709
+ }
710
+ } // Read this value AFTER items have been created,
711
+ // So their actual sizes (if variable) are taken into consideration.
712
+
713
+
714
+ var estimatedTotalSize = getEstimatedTotalSize(this.props, this._instanceProps);
715
+ return React.createElement(outerElementType || outerTagName || 'div', {
716
+ className: className,
717
+ onScroll: onScroll,
718
+ ref: this._outerRefSetter,
719
+ style: _extends({
720
+ position: 'relative',
721
+ height: height,
722
+ width: width,
723
+ overflow: 'auto',
724
+ WebkitOverflowScrolling: 'touch',
725
+ willChange: 'transform',
726
+ direction: direction
727
+ }, style)
728
+ }, React.createElement(innerElementType || innerTagName || 'div', {
729
+ children: items,
730
+ ref: innerRef,
731
+ style: {
732
+ height: isHorizontal ? '100%' : estimatedTotalSize,
733
+ pointerEvents: isScrolling ? 'none' : undefined,
734
+ width: isHorizontal ? estimatedTotalSize : '100%'
735
+ }
736
+ }));
737
+ };
738
+
739
+ _proto._callPropsCallbacks = function _callPropsCallbacks() {
740
+ if (typeof this.props.onItemsRendered === 'function') {
741
+ var itemCount = this.props.itemCount;
742
+
743
+ if (itemCount > 0) {
744
+ var _this$_getRangeToRend2 = this._getRangeToRender(),
745
+ _overscanStartIndex = _this$_getRangeToRend2[0],
746
+ _overscanStopIndex = _this$_getRangeToRend2[1],
747
+ _visibleStartIndex = _this$_getRangeToRend2[2],
748
+ _visibleStopIndex = _this$_getRangeToRend2[3];
749
+
750
+ this._callOnItemsRendered(_overscanStartIndex, _overscanStopIndex, _visibleStartIndex, _visibleStopIndex);
751
+ }
752
+ }
753
+
754
+ if (typeof this.props.onScroll === 'function') {
755
+ var _this$state2 = this.state,
756
+ _scrollDirection = _this$state2.scrollDirection,
757
+ _scrollOffset = _this$state2.scrollOffset,
758
+ _scrollUpdateWasRequested = _this$state2.scrollUpdateWasRequested;
759
+
760
+ this._callOnScroll(_scrollDirection, _scrollOffset, _scrollUpdateWasRequested);
761
+ }
762
+ } // Lazily create and cache item styles while scrolling,
763
+ // So that pure component sCU will prevent re-renders.
764
+ // We maintain this cache, and pass a style prop rather than index,
765
+ // So that List can clear cached styles and force item re-render if necessary.
766
+ ;
767
+
768
+ _proto._getRangeToRender = function _getRangeToRender() {
769
+ var _this$props6 = this.props,
770
+ itemCount = _this$props6.itemCount,
771
+ overscanCount = _this$props6.overscanCount;
772
+ var _this$state3 = this.state,
773
+ isScrolling = _this$state3.isScrolling,
774
+ scrollDirection = _this$state3.scrollDirection,
775
+ scrollOffset = _this$state3.scrollOffset;
776
+
777
+ if (itemCount === 0) {
778
+ return [0, 0, 0, 0];
779
+ }
780
+
781
+ var startIndex = getStartIndexForOffset(this.props, scrollOffset, this._instanceProps);
782
+ var stopIndex = getStopIndexForStartIndex(this.props, startIndex, scrollOffset, this._instanceProps); // Overscan by one item in each direction so that tab/focus works.
783
+ // If there isn't at least one extra item, tab loops back around.
784
+
785
+ var overscanBackward = !isScrolling || scrollDirection === 'backward' ? Math.max(1, overscanCount) : 1;
786
+ var overscanForward = !isScrolling || scrollDirection === 'forward' ? Math.max(1, overscanCount) : 1;
787
+ return [Math.max(0, startIndex - overscanBackward), Math.max(0, Math.min(itemCount - 1, stopIndex + overscanForward)), startIndex, stopIndex];
788
+ };
789
+
790
+ return List;
791
+ }(React.PureComponent), _class.defaultProps = {
792
+ direction: 'ltr',
793
+ itemData: undefined,
794
+ layout: 'vertical',
795
+ overscanCount: 2,
796
+ useIsScrolling: false
797
+ }, _class;
798
+ } // NOTE: I considered further wrapping individual items with a pure ListItem component.
799
+ // This would avoid ever calling the render function for the same index more than once,
800
+ // But it would also add the overhead of a lot of components/fibers.
801
+ // I assume people already do this (render function returning a class component),
802
+ // So my doing it would just unnecessarily double the wrappers.
803
+
804
+ var validateSharedProps$1 = function validateSharedProps(_ref2, _ref3) {
805
+ var children = _ref2.children,
806
+ direction = _ref2.direction,
807
+ height = _ref2.height,
808
+ layout = _ref2.layout,
809
+ innerTagName = _ref2.innerTagName,
810
+ outerTagName = _ref2.outerTagName,
811
+ width = _ref2.width;
812
+ var instance = _ref3.instance;
813
+
814
+ if (process.env.NODE_ENV !== 'production') {
815
+ if (innerTagName != null || outerTagName != null) {
816
+ if (devWarningsTagName$1 && !devWarningsTagName$1.has(instance)) {
817
+ devWarningsTagName$1.add(instance);
818
+ console.warn('The innerTagName and outerTagName props have been deprecated. ' + 'Please use the innerElementType and outerElementType props instead.');
819
+ }
820
+ } // TODO Deprecate direction "horizontal"
821
+
822
+
823
+ var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
824
+
825
+ switch (direction) {
826
+ case 'horizontal':
827
+ case 'vertical':
828
+ if (devWarningsDirection && !devWarningsDirection.has(instance)) {
829
+ devWarningsDirection.add(instance);
830
+ console.warn('The direction prop should be either "ltr" (default) or "rtl". ' + 'Please use the layout prop to specify "vertical" (default) or "horizontal" orientation.');
831
+ }
832
+
833
+ break;
834
+
835
+ case 'ltr':
836
+ case 'rtl':
837
+ // Valid values
838
+ break;
839
+
840
+ default:
841
+ throw Error('An invalid "direction" prop has been specified. ' + 'Value should be either "ltr" or "rtl". ' + ("\"" + direction + "\" was specified."));
842
+ }
843
+
844
+ switch (layout) {
845
+ case 'horizontal':
846
+ case 'vertical':
847
+ // Valid values
848
+ break;
849
+
850
+ default:
851
+ throw Error('An invalid "layout" prop has been specified. ' + 'Value should be either "horizontal" or "vertical". ' + ("\"" + layout + "\" was specified."));
852
+ }
853
+
854
+ if (children == null) {
855
+ throw Error('An invalid "children" prop has been specified. ' + 'Value should be a React component. ' + ("\"" + (children === null ? 'null' : typeof children) + "\" was specified."));
856
+ }
857
+
858
+ if (isHorizontal && typeof width !== 'number') {
859
+ throw Error('An invalid "width" prop has been specified. ' + 'Horizontal lists must specify a number for width. ' + ("\"" + (width === null ? 'null' : typeof width) + "\" was specified."));
860
+ } else if (!isHorizontal && typeof height !== 'number') {
861
+ throw Error('An invalid "height" prop has been specified. ' + 'Vertical lists must specify a number for height. ' + ("\"" + (height === null ? 'null' : typeof height) + "\" was specified."));
862
+ }
863
+ }
864
+ };
865
+
866
+ var FixedSizeList = /*#__PURE__*/createListComponent({
867
+ getItemOffset: function getItemOffset(_ref, index) {
868
+ var itemSize = _ref.itemSize;
869
+ return index * itemSize;
870
+ },
871
+ getItemSize: function getItemSize(_ref2, index) {
872
+ var itemSize = _ref2.itemSize;
873
+ return itemSize;
874
+ },
875
+ getEstimatedTotalSize: function getEstimatedTotalSize(_ref3) {
876
+ var itemCount = _ref3.itemCount,
877
+ itemSize = _ref3.itemSize;
878
+ return itemSize * itemCount;
879
+ },
880
+ getOffsetForIndexAndAlignment: function getOffsetForIndexAndAlignment(_ref4, index, align, scrollOffset, instanceProps, scrollbarSize) {
881
+ var direction = _ref4.direction,
882
+ height = _ref4.height,
883
+ itemCount = _ref4.itemCount,
884
+ itemSize = _ref4.itemSize,
885
+ layout = _ref4.layout,
886
+ width = _ref4.width;
887
+ // TODO Deprecate direction "horizontal"
888
+ var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
889
+ var size = isHorizontal ? width : height;
890
+ var lastItemOffset = Math.max(0, itemCount * itemSize - size);
891
+ var maxOffset = Math.min(lastItemOffset, index * itemSize);
892
+ var minOffset = Math.max(0, index * itemSize - size + itemSize + scrollbarSize);
893
+
894
+ if (align === 'smart') {
895
+ if (scrollOffset >= minOffset - size && scrollOffset <= maxOffset + size) {
896
+ align = 'auto';
897
+ } else {
898
+ align = 'center';
899
+ }
900
+ }
901
+
902
+ switch (align) {
903
+ case 'start':
904
+ return maxOffset;
905
+
906
+ case 'end':
907
+ return minOffset;
908
+
909
+ case 'center':
910
+ {
911
+ // "Centered" offset is usually the average of the min and max.
912
+ // But near the edges of the list, this doesn't hold true.
913
+ var middleOffset = Math.round(minOffset + (maxOffset - minOffset) / 2);
914
+
915
+ if (middleOffset < Math.ceil(size / 2)) {
916
+ return 0; // near the beginning
917
+ } else if (middleOffset > lastItemOffset + Math.floor(size / 2)) {
918
+ return lastItemOffset; // near the end
919
+ } else {
920
+ return middleOffset;
921
+ }
922
+ }
923
+
924
+ case 'auto':
925
+ default:
926
+ if (scrollOffset >= minOffset && scrollOffset <= maxOffset) {
927
+ return scrollOffset;
928
+ } else if (scrollOffset < minOffset) {
929
+ return minOffset;
930
+ } else {
931
+ return maxOffset;
932
+ }
933
+
934
+ }
935
+ },
936
+ getStartIndexForOffset: function getStartIndexForOffset(_ref5, offset) {
937
+ var itemCount = _ref5.itemCount,
938
+ itemSize = _ref5.itemSize;
939
+ return Math.max(0, Math.min(itemCount - 1, Math.floor(offset / itemSize)));
940
+ },
941
+ getStopIndexForStartIndex: function getStopIndexForStartIndex(_ref6, startIndex, scrollOffset) {
942
+ var direction = _ref6.direction,
943
+ height = _ref6.height,
944
+ itemCount = _ref6.itemCount,
945
+ itemSize = _ref6.itemSize,
946
+ layout = _ref6.layout,
947
+ width = _ref6.width;
948
+ // TODO Deprecate direction "horizontal"
949
+ var isHorizontal = direction === 'horizontal' || layout === 'horizontal';
950
+ var offset = startIndex * itemSize;
951
+ var size = isHorizontal ? width : height;
952
+ var numVisibleItems = Math.ceil((size + scrollOffset - offset) / itemSize);
953
+ return Math.max(0, Math.min(itemCount - 1, startIndex + numVisibleItems - 1 // -1 is because stop index is inclusive
954
+ ));
955
+ },
956
+ initInstanceProps: function initInstanceProps(props) {// Noop
957
+ },
958
+ shouldResetStyleCacheOnItemSizeChange: true,
959
+ validateProps: function validateProps(_ref7) {
960
+ var itemSize = _ref7.itemSize;
961
+
962
+ if (process.env.NODE_ENV !== 'production') {
963
+ if (typeof itemSize !== 'number') {
964
+ throw Error('An invalid "itemSize" prop has been specified. ' + 'Value should be a number. ' + ("\"" + (itemSize === null ? 'null' : typeof itemSize) + "\" was specified."));
965
+ }
966
+ }
967
+ }
968
+ });
969
+
36
970
  // Class component
37
971
  class ResponsiveTable extends React.Component {
38
972
  constructor(props) {
39
973
  super(props);
974
+ this.tableContainerRef = React.createRef();
40
975
  this.handleResize = () => {
41
976
  this.setState({
42
977
  isMobile: window.innerWidth <= this.mobileBreakpoint,
@@ -44,6 +979,8 @@ class ResponsiveTable extends React.Component {
44
979
  };
45
980
  this.state = {
46
981
  isMobile: false,
982
+ processedData: props.data,
983
+ isLoadingMore: false,
47
984
  };
48
985
  this.debouncedResize = this.debounce(this.handleResize, 200);
49
986
  }
@@ -58,8 +995,8 @@ class ResponsiveTable extends React.Component {
58
995
  };
59
996
  }
60
997
  get data() {
61
- if (Array.isArray(this.props.data) && this.props.data.length > 0) {
62
- return this.props.data;
998
+ if (Array.isArray(this.state.processedData) && this.state.processedData.length > 0) {
999
+ return this.state.processedData;
63
1000
  }
64
1001
  else {
65
1002
  return [];
@@ -80,10 +1017,66 @@ class ResponsiveTable extends React.Component {
80
1017
  componentDidMount() {
81
1018
  this.handleResize(); // Initial check
82
1019
  window.addEventListener('resize', this.debouncedResize);
1020
+ this.initializePlugins();
83
1021
  }
84
1022
  componentWillUnmount() {
85
1023
  window.removeEventListener('resize', this.debouncedResize);
86
1024
  }
1025
+ componentDidUpdate(prevProps) {
1026
+ var _a, _b, _c;
1027
+ if (prevProps.data !== this.props.data) {
1028
+ this.processData();
1029
+ }
1030
+ // Handle infinite scroll loading
1031
+ if (((_a = this.props.infiniteScrollProps) === null || _a === void 0 ? void 0 : _a.enableInfiniteScroll) && ((_b = this.props.infiniteScrollProps) === null || _b === void 0 ? void 0 : _b.hasMore) && !this.state.isLoadingMore && ((_c = this.props.infiniteScrollProps) === null || _c === void 0 ? void 0 : _c.onLoadMore)) ;
1032
+ }
1033
+ initializePlugins() {
1034
+ var _a, _b;
1035
+ const activePlugins = [];
1036
+ // Add explicitly provided plugins first
1037
+ if (this.props.plugins) {
1038
+ activePlugins.push(...this.props.plugins);
1039
+ }
1040
+ // Automatically add FilterPlugin if filterProps are provided and not already present
1041
+ if (((_a = this.props.filterProps) === null || _a === void 0 ? void 0 : _a.showFilter) && !activePlugins.some(p => p.id === 'filter')) {
1042
+ activePlugins.push(new FilterPlugin());
1043
+ }
1044
+ // Automatically add InfiniteScrollPlugin if infiniteScrollProps are provided and not already present
1045
+ if (((_b = this.props.infiniteScrollProps) === null || _b === void 0 ? void 0 : _b.enableInfiniteScroll) && !activePlugins.some(p => p.id === 'infinite-scroll')) {
1046
+ activePlugins.push(new InfiniteScrollPlugin());
1047
+ }
1048
+ activePlugins.forEach((plugin) => {
1049
+ if (plugin.onPluginInit) {
1050
+ plugin.onPluginInit({
1051
+ getData: () => this.props.data,
1052
+ forceUpdate: () => this.processData(),
1053
+ getScrollableElement: () => this.tableContainerRef.current,
1054
+ infiniteScrollProps: this.props.infiniteScrollProps,
1055
+ filterProps: this.props.filterProps,
1056
+ columnDefinitions: this.props.columnDefinitions,
1057
+ });
1058
+ }
1059
+ });
1060
+ // Process data with all active plugins
1061
+ let processedData = [...this.props.data];
1062
+ activePlugins.forEach((plugin) => {
1063
+ if (plugin.processData) {
1064
+ processedData = plugin.processData(processedData);
1065
+ }
1066
+ });
1067
+ this.setState({ processedData });
1068
+ }
1069
+ processData() {
1070
+ let processedData = [...this.props.data];
1071
+ if (this.props.plugins) {
1072
+ this.props.plugins.forEach((plugin) => {
1073
+ if (plugin.processData) {
1074
+ processedData = plugin.processData(processedData);
1075
+ }
1076
+ });
1077
+ }
1078
+ this.setState({ processedData });
1079
+ }
87
1080
  getColumnDefinition(columnDefinition, rowIndex) {
88
1081
  if (!this.hasData) {
89
1082
  return { displayLabel: '', cellRenderer: () => '' };
@@ -175,29 +1168,41 @@ class ResponsiveTable extends React.Component {
175
1168
  }
176
1169
  get mobileView() {
177
1170
  return (React.createElement("div", null,
178
- this.data.map((row, rowIndex) => (React.createElement("div", { key: rowIndex, className: `${styles['card']} ${this.props.animateOnLoad ? styles.animatedRow : ''}`, style: { animationDelay: `${rowIndex * 0.05}s` }, onClick: (e) => {
179
- this.rowClickFunction(row);
180
- e.stopPropagation();
181
- e.preventDefault();
182
- } },
183
- React.createElement("div", { className: styles['card-header'] }, " "),
184
- React.createElement("div", { className: styles['card-body'] }, this.props.columnDefinitions.map((columnDefinition, colIndex) => {
185
- const colDef = this.getColumnDefinition(columnDefinition, rowIndex);
186
- const onHeaderClickCallback = this.onHeaderClickCallback(colDef);
187
- const clickableHeaderClassName = this.getClickableHeaderClassName(onHeaderClickCallback, colDef);
188
- return (React.createElement("div", { key: colIndex, className: styles['card-row'] },
189
- React.createElement("p", null,
190
- React.createElement("span", { className: `${styles['card-label']} ${clickableHeaderClassName}`, onClick: onHeaderClickCallback ? () => onHeaderClickCallback(colDef.interactivity.id) : undefined }, colDef.displayLabel),
191
- React.createElement("span", { className: styles['card-value'] }, colDef.cellRenderer(row)))));
192
- }))))),
1171
+ this.data.map((row, rowIndex) => {
1172
+ var _a;
1173
+ return (React.createElement("div", { key: rowIndex, className: `${styles['card']} ${((_a = this.props.animationProps) === null || _a === void 0 ? void 0 : _a.animateOnLoad) ? styles.animatedRow : ''}`, style: { animationDelay: `${rowIndex * 0.05}s` }, onClick: (e) => {
1174
+ this.rowClickFunction(row);
1175
+ e.stopPropagation();
1176
+ e.preventDefault();
1177
+ } },
1178
+ React.createElement("div", { className: styles['card-header'] }, " "),
1179
+ React.createElement("div", { className: styles['card-body'] }, this.props.columnDefinitions.map((columnDefinition, colIndex) => {
1180
+ const colDef = this.getColumnDefinition(columnDefinition, rowIndex);
1181
+ const onHeaderClickCallback = this.onHeaderClickCallback(colDef);
1182
+ const clickableHeaderClassName = this.getClickableHeaderClassName(onHeaderClickCallback, colDef);
1183
+ return (React.createElement("div", { key: colIndex, className: styles['card-row'] },
1184
+ React.createElement("p", null,
1185
+ React.createElement("span", { className: `${styles['card-label']} ${clickableHeaderClassName}`, onClick: onHeaderClickCallback ? () => onHeaderClickCallback(colDef.interactivity.id) : undefined }, colDef.displayLabel),
1186
+ React.createElement("span", { className: styles['card-value'] }, colDef.cellRenderer(row)))));
1187
+ }))));
1188
+ }),
193
1189
  this.mobileFooter));
194
1190
  }
195
1191
  get largeScreenView() {
1192
+ var _a;
196
1193
  const useFixedHeaders = this.props.maxHeight ? true : false;
197
1194
  const fixedHeadersStyle = useFixedHeaders
198
1195
  ? { maxHeight: this.props.maxHeight, overflowY: 'auto' }
199
1196
  : {};
200
- return (React.createElement("div", { style: fixedHeadersStyle },
1197
+ const Row = ({ index, style }) => {
1198
+ var _a;
1199
+ const row = this.data[index];
1200
+ if (!row)
1201
+ return null; // Should not happen with correct item count
1202
+ return (React.createElement("tr", { key: index, className: ((_a = this.props.animationProps) === null || _a === void 0 ? void 0 : _a.animateOnLoad) ? styles.animatedRow : '', style: Object.assign(Object.assign({}, style), { animationDelay: `${index * 0.05}s` }) }, this.props.columnDefinitions.map((columnDefinition, colIndex) => (React.createElement("td", { onClick: () => this.rowClickFunction(row), key: colIndex },
1203
+ React.createElement("span", { style: Object.assign({}, this.rowClickStyle) }, this.getColumnDefinition(columnDefinition, index).cellRenderer(row)))))));
1204
+ };
1205
+ return (React.createElement("div", { style: fixedHeadersStyle, ref: this.tableContainerRef },
201
1206
  React.createElement("table", { className: styles['responsiveTable'], style: { zIndex: -1 } },
202
1207
  React.createElement("thead", null,
203
1208
  React.createElement("tr", null, this.props.columnDefinitions.map((columnDefinition, colIndex) => {
@@ -207,23 +1212,50 @@ class ResponsiveTable extends React.Component {
207
1212
  ? () => onHeaderClickCallback(this.getColumnDefinition(columnDefinition, 0).interactivity.id)
208
1213
  : undefined }, this.getColumnDefinition(columnDefinition, 0).displayLabel));
209
1214
  }))),
210
- React.createElement("tbody", null, this.data.map((row, rowIndex) => (React.createElement("tr", { key: rowIndex, className: this.props.animateOnLoad ? styles.animatedRow : '', style: { animationDelay: `${rowIndex * 0.05}s` } }, this.props.columnDefinitions.map((columnDefinition, colIndex) => (React.createElement("td", { onClick: () => this.rowClickFunction(row), key: colIndex },
211
- React.createElement("span", { style: Object.assign({}, this.rowClickStyle) }, this.getColumnDefinition(columnDefinition, rowIndex).cellRenderer(row))))))))),
212
- this.tableFooter)));
1215
+ React.createElement("tbody", null, ((_a = this.props.infiniteScrollProps) === null || _a === void 0 ? void 0 : _a.enableInfiniteScroll) ? (React.createElement(FixedSizeList, { height: fixedHeadersStyle.maxHeight ? (typeof fixedHeadersStyle.maxHeight === 'string' ? parseFloat(fixedHeadersStyle.maxHeight) : fixedHeadersStyle.maxHeight) : 500, itemCount: this.data.length, itemSize: 50, width: '100%', outerRef: this.tableContainerRef }, Row)) : (this.data.map((row, rowIndex) => {
1216
+ var _a;
1217
+ return (React.createElement("tr", { key: rowIndex, className: ((_a = this.props.animationProps) === null || _a === void 0 ? void 0 : _a.animateOnLoad) ? styles.animatedRow : '', style: { animationDelay: `${rowIndex * 0.05}s` } }, this.props.columnDefinitions.map((columnDefinition, colIndex) => (React.createElement("td", { onClick: () => this.rowClickFunction(row), key: colIndex },
1218
+ React.createElement("span", { style: Object.assign({}, this.rowClickStyle) }, this.getColumnDefinition(columnDefinition, rowIndex).cellRenderer(row)))))));
1219
+ }))),
1220
+ this.tableFooter),
1221
+ this.renderPluginFooters()));
213
1222
  }
214
- render() {
215
- if (this.props.isLoading) {
216
- return this.skeletonView;
1223
+ renderPluginHeaders() {
1224
+ if (!this.props.plugins) {
1225
+ return null;
217
1226
  }
218
- if (!this.hasData) {
219
- return this.noDataComponent;
1227
+ return this.props.plugins.map((plugin) => {
1228
+ if (plugin.renderHeader) {
1229
+ return React.createElement("div", { key: plugin.id }, plugin.renderHeader());
1230
+ }
1231
+ return null;
1232
+ });
1233
+ }
1234
+ renderPluginFooters() {
1235
+ if (!this.props.plugins) {
1236
+ return null;
220
1237
  }
221
- if (this.state.isMobile) {
222
- return this.mobileView;
1238
+ return this.props.plugins.map((plugin) => {
1239
+ if (plugin.renderFooter) {
1240
+ return React.createElement("div", { key: plugin.id + '-footer' }, plugin.renderFooter());
1241
+ }
1242
+ return null;
1243
+ });
1244
+ }
1245
+ render() {
1246
+ var _a;
1247
+ if ((_a = this.props.animationProps) === null || _a === void 0 ? void 0 : _a.isLoading) {
1248
+ return this.skeletonView;
223
1249
  }
224
- return this.largeScreenView;
1250
+ return (React.createElement("div", null,
1251
+ this.renderPluginHeaders(),
1252
+ !this.hasData && this.noDataComponent,
1253
+ this.hasData && this.state.isMobile && this.mobileView,
1254
+ this.hasData && !this.state.isMobile && this.largeScreenView));
225
1255
  }
226
1256
  }
227
1257
 
228
- module.exports = ResponsiveTable;
1258
+ exports.FilterPlugin = FilterPlugin;
1259
+ exports.InfiniteScrollPlugin = InfiniteScrollPlugin;
1260
+ exports.default = ResponsiveTable;
229
1261
  //# sourceMappingURL=index.js.map