1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.ScrollablePaneBase = void 0;
|
4 | var tslib_1 = require("tslib");
|
5 | var React = require("react");
|
6 | var Utilities_1 = require("../../Utilities");
|
7 | var ScrollablePane_types_1 = require("./ScrollablePane.types");
|
8 | var getClassNames = Utilities_1.classNamesFunction();
|
9 | var ScrollablePaneBase = (function (_super) {
|
10 | tslib_1.__extends(ScrollablePaneBase, _super);
|
11 | function ScrollablePaneBase(props) {
|
12 | var _this = _super.call(this, props) || this;
|
13 | _this._root = React.createRef();
|
14 | _this._stickyAboveRef = React.createRef();
|
15 | _this._stickyBelowRef = React.createRef();
|
16 | _this._contentContainer = React.createRef();
|
17 | _this.subscribe = function (handler) {
|
18 | _this._subscribers.add(handler);
|
19 | };
|
20 | _this.unsubscribe = function (handler) {
|
21 | _this._subscribers.delete(handler);
|
22 | };
|
23 | _this.addSticky = function (sticky) {
|
24 | _this._stickies.add(sticky);
|
25 |
|
26 | if (_this.contentContainer) {
|
27 | sticky.setDistanceFromTop(_this.contentContainer);
|
28 | _this.sortSticky(sticky);
|
29 | }
|
30 | };
|
31 | _this.removeSticky = function (sticky) {
|
32 | _this._stickies.delete(sticky);
|
33 | _this._removeStickyFromContainers(sticky);
|
34 | _this.notifySubscribers();
|
35 | };
|
36 | _this.sortSticky = function (sticky, sortAgain) {
|
37 | if (_this.stickyAbove && _this.stickyBelow) {
|
38 | if (sortAgain) {
|
39 | _this._removeStickyFromContainers(sticky);
|
40 | }
|
41 | if (sticky.canStickyTop && sticky.stickyContentTop) {
|
42 | _this._addToStickyContainer(sticky, _this.stickyAbove, sticky.stickyContentTop);
|
43 | }
|
44 | if (sticky.canStickyBottom && sticky.stickyContentBottom) {
|
45 | _this._addToStickyContainer(sticky, _this.stickyBelow, sticky.stickyContentBottom);
|
46 | }
|
47 | }
|
48 | };
|
49 | _this.updateStickyRefHeights = function () {
|
50 | var stickyItems = _this._stickies;
|
51 | var stickyTopHeight = 0;
|
52 | var stickyBottomHeight = 0;
|
53 | stickyItems.forEach(function (sticky) {
|
54 | var _a = sticky.state, isStickyTop = _a.isStickyTop, isStickyBottom = _a.isStickyBottom;
|
55 | if (sticky.nonStickyContent) {
|
56 | if (isStickyTop) {
|
57 | stickyTopHeight += sticky.nonStickyContent.offsetHeight;
|
58 | }
|
59 | if (isStickyBottom) {
|
60 | stickyBottomHeight += sticky.nonStickyContent.offsetHeight;
|
61 | }
|
62 | _this._checkStickyStatus(sticky);
|
63 | }
|
64 | });
|
65 | _this.setState({
|
66 | stickyTopHeight: stickyTopHeight,
|
67 | stickyBottomHeight: stickyBottomHeight,
|
68 | });
|
69 | };
|
70 | _this.notifySubscribers = function () {
|
71 | if (_this.contentContainer) {
|
72 | _this._subscribers.forEach(function (handle) {
|
73 |
|
74 | handle(_this.contentContainer, _this.stickyBelow);
|
75 | });
|
76 | }
|
77 | };
|
78 | _this.getScrollPosition = function () {
|
79 | if (_this.contentContainer) {
|
80 | return _this.contentContainer.scrollTop;
|
81 | }
|
82 | return 0;
|
83 | };
|
84 | _this.syncScrollSticky = function (sticky) {
|
85 | if (sticky && _this.contentContainer) {
|
86 | sticky.syncScroll(_this.contentContainer);
|
87 | }
|
88 | };
|
89 | _this._getScrollablePaneContext = function () {
|
90 | return {
|
91 | scrollablePane: {
|
92 | subscribe: _this.subscribe,
|
93 | unsubscribe: _this.unsubscribe,
|
94 | addSticky: _this.addSticky,
|
95 | removeSticky: _this.removeSticky,
|
96 | updateStickyRefHeights: _this.updateStickyRefHeights,
|
97 | sortSticky: _this.sortSticky,
|
98 | notifySubscribers: _this.notifySubscribers,
|
99 | syncScrollSticky: _this.syncScrollSticky,
|
100 | },
|
101 | };
|
102 | };
|
103 | _this._addToStickyContainer = function (sticky, stickyContainer, stickyContentToAdd) {
|
104 |
|
105 | if (!stickyContainer.children.length) {
|
106 | stickyContainer.appendChild(stickyContentToAdd);
|
107 | }
|
108 | else {
|
109 |
|
110 | if (!stickyContainer.contains(stickyContentToAdd)) {
|
111 | var stickyChildrenElements_1 = [].slice.call(stickyContainer.children);
|
112 | var stickyList_1 = [];
|
113 |
|
114 |
|
115 | _this._stickies.forEach(function (stickyItem) {
|
116 | if (stickyContainer === _this.stickyAbove && sticky.canStickyTop) {
|
117 | stickyList_1.push(stickyItem);
|
118 | }
|
119 | else if (sticky.canStickyBottom) {
|
120 | stickyList_1.push(stickyItem);
|
121 | }
|
122 | });
|
123 | var stickyListSorted = stickyList_1
|
124 | .sort(function (a, b) {
|
125 | return (a.state.distanceFromTop || 0) - (b.state.distanceFromTop || 0);
|
126 | })
|
127 | .filter(function (item) {
|
128 | var stickyContent = stickyContainer === _this.stickyAbove ? item.stickyContentTop : item.stickyContentBottom;
|
129 | if (stickyContent) {
|
130 | return stickyChildrenElements_1.indexOf(stickyContent) > -1;
|
131 | }
|
132 | return false;
|
133 | });
|
134 |
|
135 | var targetStickyToAppendBefore = undefined;
|
136 | for (var _i = 0, stickyListSorted_1 = stickyListSorted; _i < stickyListSorted_1.length; _i++) {
|
137 | var stickyListItem = stickyListSorted_1[_i];
|
138 | if ((stickyListItem.state.distanceFromTop || 0) >= (sticky.state.distanceFromTop || 0)) {
|
139 | targetStickyToAppendBefore = stickyListItem;
|
140 | break;
|
141 | }
|
142 | }
|
143 |
|
144 |
|
145 | var targetContainer = null;
|
146 | if (targetStickyToAppendBefore) {
|
147 | targetContainer =
|
148 | stickyContainer === _this.stickyAbove
|
149 | ? targetStickyToAppendBefore.stickyContentTop
|
150 | : targetStickyToAppendBefore.stickyContentBottom;
|
151 | }
|
152 | stickyContainer.insertBefore(stickyContentToAdd, targetContainer);
|
153 | }
|
154 | }
|
155 | };
|
156 | _this._removeStickyFromContainers = function (sticky) {
|
157 | if (_this.stickyAbove && sticky.stickyContentTop && _this.stickyAbove.contains(sticky.stickyContentTop)) {
|
158 | _this.stickyAbove.removeChild(sticky.stickyContentTop);
|
159 | }
|
160 | if (_this.stickyBelow && sticky.stickyContentBottom && _this.stickyBelow.contains(sticky.stickyContentBottom)) {
|
161 | _this.stickyBelow.removeChild(sticky.stickyContentBottom);
|
162 | }
|
163 | };
|
164 | _this._onWindowResize = function () {
|
165 | var scrollbarWidth = _this._getScrollbarWidth();
|
166 | var scrollbarHeight = _this._getScrollbarHeight();
|
167 | _this.setState({
|
168 | scrollbarWidth: scrollbarWidth,
|
169 | scrollbarHeight: scrollbarHeight,
|
170 | });
|
171 | _this.notifySubscribers();
|
172 | };
|
173 | _this._getStickyContainerStyle = function (height, isTop) {
|
174 | return tslib_1.__assign(tslib_1.__assign({ height: height }, (Utilities_1.getRTL(_this.props.theme)
|
175 | ? {
|
176 | right: '0',
|
177 | left: (_this.state.scrollbarWidth || _this._getScrollbarWidth() || 0) + "px",
|
178 | }
|
179 | : {
|
180 | left: '0',
|
181 | right: (_this.state.scrollbarWidth || _this._getScrollbarWidth() || 0) + "px",
|
182 | })), (isTop
|
183 | ? {
|
184 | top: '0',
|
185 | }
|
186 | : {
|
187 | bottom: (_this.state.scrollbarHeight || _this._getScrollbarHeight() || 0) + "px",
|
188 | }));
|
189 | };
|
190 | _this._onScroll = function () {
|
191 | var contentContainer = _this.contentContainer;
|
192 | if (contentContainer) {
|
193 | _this._stickies.forEach(function (sticky) {
|
194 | sticky.syncScroll(contentContainer);
|
195 | });
|
196 | }
|
197 | _this._notifyThrottled();
|
198 | };
|
199 | _this._subscribers = new Set();
|
200 | _this._stickies = new Set();
|
201 | Utilities_1.initializeComponentRef(_this);
|
202 | _this._async = new Utilities_1.Async(_this);
|
203 | _this._events = new Utilities_1.EventGroup(_this);
|
204 | _this.state = {
|
205 | stickyTopHeight: 0,
|
206 | stickyBottomHeight: 0,
|
207 | scrollbarWidth: 0,
|
208 | scrollbarHeight: 0,
|
209 | };
|
210 | _this._notifyThrottled = _this._async.throttle(_this.notifySubscribers, 50);
|
211 | return _this;
|
212 | }
|
213 | Object.defineProperty(ScrollablePaneBase.prototype, "root", {
|
214 | get: function () {
|
215 | return this._root.current;
|
216 | },
|
217 | enumerable: false,
|
218 | configurable: true
|
219 | });
|
220 | Object.defineProperty(ScrollablePaneBase.prototype, "stickyAbove", {
|
221 | get: function () {
|
222 | return this._stickyAboveRef.current;
|
223 | },
|
224 | enumerable: false,
|
225 | configurable: true
|
226 | });
|
227 | Object.defineProperty(ScrollablePaneBase.prototype, "stickyBelow", {
|
228 | get: function () {
|
229 | return this._stickyBelowRef.current;
|
230 | },
|
231 | enumerable: false,
|
232 | configurable: true
|
233 | });
|
234 | Object.defineProperty(ScrollablePaneBase.prototype, "contentContainer", {
|
235 | get: function () {
|
236 | return this._contentContainer.current;
|
237 | },
|
238 | enumerable: false,
|
239 | configurable: true
|
240 | });
|
241 | ScrollablePaneBase.prototype.componentDidMount = function () {
|
242 | var _this = this;
|
243 | var initialScrollPosition = this.props.initialScrollPosition;
|
244 | this._events.on(this.contentContainer, 'scroll', this._onScroll);
|
245 | this._events.on(window, 'resize', this._onWindowResize);
|
246 | if (this.contentContainer && initialScrollPosition) {
|
247 | this.contentContainer.scrollTop = initialScrollPosition;
|
248 | }
|
249 |
|
250 | this.setStickiesDistanceFromTop();
|
251 | this._stickies.forEach(function (sticky) {
|
252 | _this.sortSticky(sticky);
|
253 | });
|
254 | this.notifySubscribers();
|
255 | if ('MutationObserver' in window) {
|
256 | this._mutationObserver = new MutationObserver(function (mutation) {
|
257 |
|
258 | function checkIfMutationIsSticky(mutationRecord) {
|
259 | if (this.stickyAbove !== null && this.stickyBelow !== null) {
|
260 | return this.stickyAbove.contains(mutationRecord.target) || this.stickyBelow.contains(mutationRecord.target);
|
261 | }
|
262 | return false;
|
263 | }
|
264 |
|
265 | var scrollbarHeight = _this._getScrollbarHeight();
|
266 |
|
267 | if (scrollbarHeight !== _this.state.scrollbarHeight) {
|
268 | _this.setState({
|
269 | scrollbarHeight: scrollbarHeight,
|
270 | });
|
271 | }
|
272 |
|
273 | _this.notifySubscribers();
|
274 |
|
275 | if (mutation.some(checkIfMutationIsSticky.bind(_this))) {
|
276 | _this.updateStickyRefHeights();
|
277 | }
|
278 | else {
|
279 |
|
280 | var stickyList_2 = [];
|
281 | _this._stickies.forEach(function (sticky) {
|
282 | if (sticky.root && sticky.root.contains(mutation[0].target)) {
|
283 | stickyList_2.push(sticky);
|
284 | }
|
285 | });
|
286 | if (stickyList_2.length) {
|
287 | stickyList_2.forEach(function (sticky) {
|
288 | sticky.forceUpdate();
|
289 | });
|
290 | }
|
291 | }
|
292 | });
|
293 | if (this.root) {
|
294 | this._mutationObserver.observe(this.root, {
|
295 | childList: true,
|
296 | attributes: true,
|
297 | subtree: true,
|
298 | characterData: true,
|
299 | });
|
300 | }
|
301 | }
|
302 | };
|
303 | ScrollablePaneBase.prototype.componentWillUnmount = function () {
|
304 | this._events.dispose();
|
305 | this._async.dispose();
|
306 | if (this._mutationObserver) {
|
307 | this._mutationObserver.disconnect();
|
308 | }
|
309 | };
|
310 |
|
311 | ScrollablePaneBase.prototype.shouldComponentUpdate = function (nextProps, nextState) {
|
312 | return (this.props.children !== nextProps.children ||
|
313 | this.props.initialScrollPosition !== nextProps.initialScrollPosition ||
|
314 | this.props.className !== nextProps.className ||
|
315 | this.state.stickyTopHeight !== nextState.stickyTopHeight ||
|
316 | this.state.stickyBottomHeight !== nextState.stickyBottomHeight ||
|
317 | this.state.scrollbarWidth !== nextState.scrollbarWidth ||
|
318 | this.state.scrollbarHeight !== nextState.scrollbarHeight);
|
319 | };
|
320 | ScrollablePaneBase.prototype.componentDidUpdate = function (prevProps, prevState) {
|
321 | var initialScrollPosition = this.props.initialScrollPosition;
|
322 | if (this.contentContainer &&
|
323 | typeof initialScrollPosition === 'number' &&
|
324 | prevProps.initialScrollPosition !== initialScrollPosition) {
|
325 | this.contentContainer.scrollTop = initialScrollPosition;
|
326 | }
|
327 |
|
328 | if (prevState.stickyTopHeight !== this.state.stickyTopHeight ||
|
329 | prevState.stickyBottomHeight !== this.state.stickyBottomHeight) {
|
330 | this.notifySubscribers();
|
331 | }
|
332 | this._async.setTimeout(this._onWindowResize, 0);
|
333 | };
|
334 | ScrollablePaneBase.prototype.render = function () {
|
335 | var _a = this.props, className = _a.className, scrollContainerFocus = _a.scrollContainerFocus, scrollContainerAriaLabel = _a.scrollContainerAriaLabel, theme = _a.theme, styles = _a.styles, onScroll = _a.onScroll;
|
336 | var _b = this.state, stickyTopHeight = _b.stickyTopHeight, stickyBottomHeight = _b.stickyBottomHeight;
|
337 | var classNames = getClassNames(styles, {
|
338 | theme: theme,
|
339 | className: className,
|
340 | scrollbarVisibility: this.props.scrollbarVisibility,
|
341 | });
|
342 | var scrollContainerProps = scrollContainerFocus
|
343 | ? {
|
344 | role: 'group',
|
345 | tabIndex: 0,
|
346 | 'aria-label': scrollContainerAriaLabel,
|
347 | onScroll: onScroll,
|
348 | }
|
349 | : {
|
350 | onScroll: onScroll,
|
351 | };
|
352 | return (React.createElement("div", tslib_1.__assign({}, Utilities_1.getNativeProps(tslib_1.__assign({}, this.props), Utilities_1.divProperties,
|
353 |
|
354 |
|
355 | ['onScroll']), { ref: this._root, className: classNames.root }),
|
356 | React.createElement("div", { ref: this._stickyAboveRef, className: classNames.stickyAbove, style: this._getStickyContainerStyle(stickyTopHeight, true) }),
|
357 | React.createElement("div", tslib_1.__assign({ ref: this._contentContainer }, scrollContainerProps, { className: classNames.contentContainer, "data-is-scrollable": true }),
|
358 | React.createElement(ScrollablePane_types_1.ScrollablePaneContext.Provider, { value: this._getScrollablePaneContext() }, this.props.children)),
|
359 | React.createElement("div", { className: classNames.stickyBelow, style: this._getStickyContainerStyle(stickyBottomHeight, false) },
|
360 | React.createElement("div", { ref: this._stickyBelowRef, className: classNames.stickyBelowItems }))));
|
361 | };
|
362 | ScrollablePaneBase.prototype.setStickiesDistanceFromTop = function () {
|
363 | var _this = this;
|
364 | if (this.contentContainer) {
|
365 | this._stickies.forEach(function (sticky) {
|
366 | sticky.setDistanceFromTop(_this.contentContainer);
|
367 | });
|
368 | }
|
369 | };
|
370 | ScrollablePaneBase.prototype.forceLayoutUpdate = function () {
|
371 | this._onWindowResize();
|
372 | };
|
373 | ScrollablePaneBase.prototype._checkStickyStatus = function (sticky) {
|
374 | if (this.stickyAbove && this.stickyBelow && this.contentContainer && sticky.nonStickyContent) {
|
375 |
|
376 | if (sticky.state.isStickyTop || sticky.state.isStickyBottom) {
|
377 | if (sticky.state.isStickyTop &&
|
378 | !this.stickyAbove.contains(sticky.nonStickyContent) &&
|
379 | sticky.stickyContentTop) {
|
380 | sticky.addSticky(sticky.stickyContentTop);
|
381 | }
|
382 | if (sticky.state.isStickyBottom &&
|
383 | !this.stickyBelow.contains(sticky.nonStickyContent) &&
|
384 | sticky.stickyContentBottom) {
|
385 | sticky.addSticky(sticky.stickyContentBottom);
|
386 | }
|
387 | }
|
388 | else if (!this.contentContainer.contains(sticky.nonStickyContent)) {
|
389 |
|
390 | sticky.resetSticky();
|
391 | }
|
392 | }
|
393 | };
|
394 | ScrollablePaneBase.prototype._getScrollbarWidth = function () {
|
395 | var contentContainer = this.contentContainer;
|
396 | return contentContainer ? contentContainer.offsetWidth - contentContainer.clientWidth : 0;
|
397 | };
|
398 | ScrollablePaneBase.prototype._getScrollbarHeight = function () {
|
399 | var contentContainer = this.contentContainer;
|
400 | return contentContainer ? contentContainer.offsetHeight - contentContainer.clientHeight : 0;
|
401 | };
|
402 | return ScrollablePaneBase;
|
403 | }(React.Component));
|
404 | exports.ScrollablePaneBase = ScrollablePaneBase;
|
405 |
|
\ | No newline at end of file |