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