@fullcalendar/scrollgrid 6.0.0-beta.1 → 6.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +5 -5
- package/index.cjs +22 -0
- package/index.d.ts +7 -0
- package/{main.global.js → index.global.js} +164 -261
- package/index.global.min.js +6 -0
- package/index.js +14 -0
- package/{main.cjs.js → internal.cjs} +148 -267
- package/{main.d.ts → internal.d.ts} +4 -13
- package/{main.js → internal.js} +95 -210
- package/package.json +42 -18
- package/main.global.min.js +0 -6
- package/main.js.map +0 -1
|
@@ -1,109 +1,14 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
FullCalendar Scheduler v6.0.0-beta.1
|
|
3
|
-
Docs & License: https://fullcalendar.io/scheduler
|
|
4
|
-
(c) 2022 Adam Shaw
|
|
5
|
-
*/
|
|
6
1
|
'use strict';
|
|
7
2
|
|
|
8
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
9
4
|
|
|
10
|
-
var
|
|
11
|
-
var
|
|
12
|
-
|
|
13
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
14
|
-
|
|
15
|
-
var premiumCommonPlugin__default = /*#__PURE__*/_interopDefaultLegacy(premiumCommonPlugin);
|
|
16
|
-
|
|
17
|
-
const WHEEL_EVENT_NAMES = 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ');
|
|
18
|
-
/*
|
|
19
|
-
ALSO, with the ability to disable touch
|
|
20
|
-
*/
|
|
21
|
-
class ScrollListener {
|
|
22
|
-
constructor(el) {
|
|
23
|
-
this.el = el;
|
|
24
|
-
this.emitter = new common.Emitter();
|
|
25
|
-
this.isScrolling = false;
|
|
26
|
-
this.isTouching = false; // user currently has finger down?
|
|
27
|
-
this.isRecentlyWheeled = false;
|
|
28
|
-
this.isRecentlyScrolled = false;
|
|
29
|
-
this.wheelWaiter = new common.DelayedRunner(this._handleWheelWaited.bind(this));
|
|
30
|
-
this.scrollWaiter = new common.DelayedRunner(this._handleScrollWaited.bind(this));
|
|
31
|
-
// Handlers
|
|
32
|
-
// ----------------------------------------------------------------------------------------------
|
|
33
|
-
this.handleScroll = () => {
|
|
34
|
-
this.startScroll();
|
|
35
|
-
this.emitter.trigger('scroll', this.isRecentlyWheeled, this.isTouching);
|
|
36
|
-
this.isRecentlyScrolled = true;
|
|
37
|
-
this.scrollWaiter.request(500);
|
|
38
|
-
};
|
|
39
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
40
|
-
this.handleWheel = () => {
|
|
41
|
-
this.isRecentlyWheeled = true;
|
|
42
|
-
this.wheelWaiter.request(500);
|
|
43
|
-
};
|
|
44
|
-
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
45
|
-
this.handleTouchStart = () => {
|
|
46
|
-
this.isTouching = true;
|
|
47
|
-
};
|
|
48
|
-
this.handleTouchEnd = () => {
|
|
49
|
-
this.isTouching = false;
|
|
50
|
-
// if the user ended their touch, and the scroll area wasn't moving,
|
|
51
|
-
// we consider this to be the end of the scroll.
|
|
52
|
-
if (!this.isRecentlyScrolled) {
|
|
53
|
-
this.endScroll(); // won't fire if already ended
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
el.addEventListener('scroll', this.handleScroll);
|
|
57
|
-
el.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
58
|
-
el.addEventListener('touchend', this.handleTouchEnd);
|
|
59
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
60
|
-
el.addEventListener(eventName, this.handleWheel);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
destroy() {
|
|
64
|
-
let { el } = this;
|
|
65
|
-
el.removeEventListener('scroll', this.handleScroll);
|
|
66
|
-
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
67
|
-
el.removeEventListener('touchend', this.handleTouchEnd);
|
|
68
|
-
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
69
|
-
el.removeEventListener(eventName, this.handleWheel);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
// Start / Stop
|
|
73
|
-
// ----------------------------------------------------------------------------------------------
|
|
74
|
-
startScroll() {
|
|
75
|
-
if (!this.isScrolling) {
|
|
76
|
-
this.isScrolling = true;
|
|
77
|
-
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
endScroll() {
|
|
81
|
-
if (this.isScrolling) {
|
|
82
|
-
this.emitter.trigger('scrollEnd');
|
|
83
|
-
this.isScrolling = false;
|
|
84
|
-
this.isRecentlyScrolled = true;
|
|
85
|
-
this.isRecentlyWheeled = false;
|
|
86
|
-
this.scrollWaiter.clear();
|
|
87
|
-
this.wheelWaiter.clear();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
_handleScrollWaited() {
|
|
91
|
-
this.isRecentlyScrolled = false;
|
|
92
|
-
// only end the scroll if not currently touching.
|
|
93
|
-
// if touching, the scrolling will end later, on touchend.
|
|
94
|
-
if (!this.isTouching) {
|
|
95
|
-
this.endScroll(); // won't fire if already ended
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
_handleWheelWaited() {
|
|
99
|
-
this.isRecentlyWheeled = false;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
5
|
+
var internal_cjs = require('@fullcalendar/core/internal.cjs');
|
|
6
|
+
var preact_cjs = require('@fullcalendar/core/preact.cjs');
|
|
102
7
|
|
|
103
8
|
// TODO: assume the el has no borders?
|
|
104
9
|
function getScrollCanvasOrigin(scrollEl) {
|
|
105
10
|
let rect = scrollEl.getBoundingClientRect();
|
|
106
|
-
let edges =
|
|
11
|
+
let edges = internal_cjs.computeEdges(scrollEl); // TODO: pass in isRtl?
|
|
107
12
|
return {
|
|
108
13
|
left: rect.left + edges.borderLeft + edges.scrollbarLeft - getScrollFromLeftEdge(scrollEl),
|
|
109
14
|
top: rect.top + edges.borderTop - scrollEl.scrollTop,
|
|
@@ -166,16 +71,13 @@ function detectRtlScrollSystem() {
|
|
|
166
71
|
system = 'negative'; // scroll is a negative number from the right edge
|
|
167
72
|
}
|
|
168
73
|
}
|
|
169
|
-
|
|
74
|
+
internal_cjs.removeElement(el);
|
|
170
75
|
return system;
|
|
171
76
|
}
|
|
172
77
|
|
|
173
|
-
const IS_MS_EDGE = typeof navigator !== 'undefined' && /Edge/.test(navigator.userAgent); // TODO: what about Chromeum-based Edge?
|
|
174
78
|
const STICKY_SELECTOR = '.fc-sticky';
|
|
175
79
|
/*
|
|
176
|
-
|
|
177
|
-
- support in IE11
|
|
178
|
-
- nice centering support
|
|
80
|
+
Goes beyond mere position:sticky, allows horizontal centering
|
|
179
81
|
|
|
180
82
|
REQUIREMENT: fc-sticky elements, if the fc-sticky className is taken away, should NOT have relative or absolute positioning.
|
|
181
83
|
This is because we attach the coords with JS, and the VDOM might take away the fc-sticky class but doesn't know kill the positioning.
|
|
@@ -186,41 +88,20 @@ class StickyScrolling {
|
|
|
186
88
|
constructor(scrollEl, isRtl) {
|
|
187
89
|
this.scrollEl = scrollEl;
|
|
188
90
|
this.isRtl = isRtl;
|
|
189
|
-
this.usingRelative = null;
|
|
190
91
|
this.updateSize = () => {
|
|
191
92
|
let { scrollEl } = this;
|
|
192
|
-
let els =
|
|
93
|
+
let els = internal_cjs.findElements(scrollEl, STICKY_SELECTOR);
|
|
193
94
|
let elGeoms = this.queryElGeoms(els);
|
|
194
95
|
let viewportWidth = scrollEl.clientWidth;
|
|
195
|
-
|
|
196
|
-
if (this.usingRelative) {
|
|
197
|
-
let elDestinations = this.computeElDestinations(elGeoms, viewportWidth); // read before prepPositioning
|
|
198
|
-
assignRelativePositions(els, elGeoms, elDestinations, viewportWidth, viewportHeight);
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
assignStickyPositions(els, elGeoms, viewportWidth);
|
|
202
|
-
}
|
|
96
|
+
assignStickyPositions(els, elGeoms, viewportWidth);
|
|
203
97
|
};
|
|
204
|
-
this.usingRelative =
|
|
205
|
-
!getStickySupported() || // IE11
|
|
206
|
-
// https://stackoverflow.com/questions/56835658/in-microsoft-edge-sticky-positioning-doesnt-work-when-combined-with-dir-rtl
|
|
207
|
-
(IS_MS_EDGE && isRtl);
|
|
208
|
-
if (this.usingRelative) {
|
|
209
|
-
this.listener = new ScrollListener(scrollEl);
|
|
210
|
-
this.listener.emitter.on('scrollEnd', this.updateSize);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
destroy() {
|
|
214
|
-
if (this.listener) {
|
|
215
|
-
this.listener.destroy();
|
|
216
|
-
}
|
|
217
98
|
}
|
|
218
99
|
queryElGeoms(els) {
|
|
219
100
|
let { scrollEl, isRtl } = this;
|
|
220
101
|
let canvasOrigin = getScrollCanvasOrigin(scrollEl);
|
|
221
102
|
let elGeoms = [];
|
|
222
103
|
for (let el of els) {
|
|
223
|
-
let parentBound =
|
|
104
|
+
let parentBound = internal_cjs.translateRect(internal_cjs.computeInnerRect(el.parentNode, true, true), // weird way to call this!!!
|
|
224
105
|
-canvasOrigin.left, -canvasOrigin.top);
|
|
225
106
|
let elRect = el.getBoundingClientRect();
|
|
226
107
|
let computedStyles = window.getComputedStyle(el);
|
|
@@ -233,7 +114,7 @@ class StickyScrolling {
|
|
|
233
114
|
textAlign = isRtl ? 'left' : 'right';
|
|
234
115
|
}
|
|
235
116
|
if (computedStyles.position !== 'sticky') {
|
|
236
|
-
naturalBound =
|
|
117
|
+
naturalBound = internal_cjs.translateRect(elRect, -canvasOrigin.left - (parseFloat(computedStyles.left) || 0), // could be 'auto'
|
|
237
118
|
-canvasOrigin.top - (parseFloat(computedStyles.top) || 0));
|
|
238
119
|
}
|
|
239
120
|
elGeoms.push({
|
|
@@ -246,59 +127,6 @@ class StickyScrolling {
|
|
|
246
127
|
}
|
|
247
128
|
return elGeoms;
|
|
248
129
|
}
|
|
249
|
-
// only for IE
|
|
250
|
-
computeElDestinations(elGeoms, viewportWidth) {
|
|
251
|
-
let { scrollEl } = this;
|
|
252
|
-
let viewportTop = scrollEl.scrollTop;
|
|
253
|
-
let viewportLeft = getScrollFromLeftEdge(scrollEl);
|
|
254
|
-
let viewportRight = viewportLeft + viewportWidth;
|
|
255
|
-
return elGeoms.map((elGeom) => {
|
|
256
|
-
let { elWidth, elHeight, parentBound, naturalBound } = elGeom;
|
|
257
|
-
let destLeft; // relative to canvas topleft
|
|
258
|
-
let destTop; // "
|
|
259
|
-
switch (elGeom.textAlign) {
|
|
260
|
-
case 'left':
|
|
261
|
-
destLeft = viewportLeft;
|
|
262
|
-
break;
|
|
263
|
-
case 'right':
|
|
264
|
-
destLeft = viewportRight - elWidth;
|
|
265
|
-
break;
|
|
266
|
-
case 'center':
|
|
267
|
-
destLeft = (viewportLeft + viewportRight) / 2 - elWidth / 2; /// noooo, use half-width insteadddddddd
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
destLeft = Math.min(destLeft, parentBound.right - elWidth);
|
|
271
|
-
destLeft = Math.max(destLeft, parentBound.left);
|
|
272
|
-
destTop = viewportTop;
|
|
273
|
-
destTop = Math.min(destTop, parentBound.bottom - elHeight);
|
|
274
|
-
destTop = Math.max(destTop, naturalBound.top); // better to use natural top for upper bound
|
|
275
|
-
return { left: destLeft, top: destTop };
|
|
276
|
-
});
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
function assignRelativePositions(els, elGeoms, elDestinations, viewportWidth, viewportHeight) {
|
|
280
|
-
els.forEach((el, i) => {
|
|
281
|
-
let { naturalBound, parentBound } = elGeoms[i];
|
|
282
|
-
let parentWidth = parentBound.right - parentBound.left;
|
|
283
|
-
let parentHeight = parentBound.bottom - parentBound.bottom;
|
|
284
|
-
let left;
|
|
285
|
-
let top;
|
|
286
|
-
if (parentWidth > viewportWidth ||
|
|
287
|
-
parentHeight > viewportHeight) {
|
|
288
|
-
left = elDestinations[i].left - naturalBound.left;
|
|
289
|
-
top = elDestinations[i].top - naturalBound.top;
|
|
290
|
-
}
|
|
291
|
-
else { // if parent container can be completely in view, we don't need stickiness
|
|
292
|
-
left = '';
|
|
293
|
-
top = '';
|
|
294
|
-
}
|
|
295
|
-
common.applyStyle(el, {
|
|
296
|
-
position: 'relative',
|
|
297
|
-
left,
|
|
298
|
-
right: -left,
|
|
299
|
-
top,
|
|
300
|
-
});
|
|
301
|
-
});
|
|
302
130
|
}
|
|
303
131
|
function assignStickyPositions(els, elGeoms, viewportWidth) {
|
|
304
132
|
els.forEach((el, i) => {
|
|
@@ -312,40 +140,25 @@ function assignStickyPositions(els, elGeoms, viewportWidth) {
|
|
|
312
140
|
else { // if parent container can be completely in view, we don't need stickiness
|
|
313
141
|
left = '';
|
|
314
142
|
}
|
|
315
|
-
|
|
143
|
+
internal_cjs.applyStyle(el, {
|
|
316
144
|
left,
|
|
317
145
|
right: left,
|
|
318
146
|
top: 0,
|
|
319
147
|
});
|
|
320
148
|
});
|
|
321
149
|
}
|
|
322
|
-
let _isStickySupported;
|
|
323
|
-
function getStickySupported() {
|
|
324
|
-
if (_isStickySupported == null) {
|
|
325
|
-
_isStickySupported = computeStickySupported();
|
|
326
|
-
}
|
|
327
|
-
return _isStickySupported;
|
|
328
|
-
}
|
|
329
|
-
function computeStickySupported() {
|
|
330
|
-
let el = document.createElement('div');
|
|
331
|
-
el.style.position = 'sticky';
|
|
332
|
-
document.body.appendChild(el);
|
|
333
|
-
let val = window.getComputedStyle(el).position;
|
|
334
|
-
common.removeElement(el);
|
|
335
|
-
return val === 'sticky';
|
|
336
|
-
}
|
|
337
150
|
|
|
338
|
-
class ClippedScroller extends
|
|
151
|
+
class ClippedScroller extends internal_cjs.BaseComponent {
|
|
339
152
|
constructor() {
|
|
340
153
|
super(...arguments);
|
|
341
|
-
this.elRef =
|
|
154
|
+
this.elRef = preact_cjs.createRef();
|
|
342
155
|
this.state = {
|
|
343
156
|
xScrollbarWidth: 0,
|
|
344
157
|
yScrollbarWidth: 0,
|
|
345
158
|
};
|
|
346
159
|
this.handleScroller = (scroller) => {
|
|
347
160
|
this.scroller = scroller;
|
|
348
|
-
|
|
161
|
+
internal_cjs.setRef(this.props.scrollerRef, scroller);
|
|
349
162
|
};
|
|
350
163
|
this.handleSizing = () => {
|
|
351
164
|
let { props } = this;
|
|
@@ -359,7 +172,7 @@ class ClippedScroller extends common.BaseComponent {
|
|
|
359
172
|
}
|
|
360
173
|
render() {
|
|
361
174
|
let { props, state, context } = this;
|
|
362
|
-
let isScrollbarOnLeft = context.isRtl &&
|
|
175
|
+
let isScrollbarOnLeft = context.isRtl && internal_cjs.getIsRtlScrollbarOnLeft();
|
|
363
176
|
let overcomeLeft = 0;
|
|
364
177
|
let overcomeRight = 0;
|
|
365
178
|
let overcomeBottom = 0;
|
|
@@ -376,8 +189,8 @@ class ClippedScroller extends common.BaseComponent {
|
|
|
376
189
|
}
|
|
377
190
|
}
|
|
378
191
|
}
|
|
379
|
-
return (
|
|
380
|
-
|
|
192
|
+
return (preact_cjs.createElement("div", { ref: this.elRef, className: 'fc-scroller-harness' + (props.liquid ? ' fc-scroller-harness-liquid' : '') },
|
|
193
|
+
preact_cjs.createElement(internal_cjs.Scroller, { ref: this.handleScroller, elRef: this.props.scrollerElRef, overflowX: props.overflowX === 'scroll-hidden' ? 'scroll' : props.overflowX, overflowY: props.overflowY === 'scroll-hidden' ? 'scroll' : props.overflowY, overcomeLeft: overcomeLeft, overcomeRight: overcomeRight, overcomeBottom: overcomeBottom, maxHeight: typeof props.maxHeight === 'number'
|
|
381
194
|
? (props.maxHeight + (props.overflowX === 'scroll-hidden' ? state.xScrollbarWidth : 0))
|
|
382
195
|
: '', liquid: props.liquid, liquidIsAbsolute: true }, props.children)));
|
|
383
196
|
}
|
|
@@ -386,7 +199,7 @@ class ClippedScroller extends common.BaseComponent {
|
|
|
386
199
|
this.context.addResizeHandler(this.handleSizing);
|
|
387
200
|
}
|
|
388
201
|
componentDidUpdate(prevProps) {
|
|
389
|
-
if (!
|
|
202
|
+
if (!internal_cjs.isPropsEqual(prevProps, this.props)) { // an external change?
|
|
390
203
|
this.handleSizing();
|
|
391
204
|
}
|
|
392
205
|
}
|
|
@@ -401,6 +214,92 @@ class ClippedScroller extends common.BaseComponent {
|
|
|
401
214
|
}
|
|
402
215
|
}
|
|
403
216
|
|
|
217
|
+
const WHEEL_EVENT_NAMES = 'wheel mousewheel DomMouseScroll MozMousePixelScroll'.split(' ');
|
|
218
|
+
/*
|
|
219
|
+
ALSO, with the ability to disable touch
|
|
220
|
+
*/
|
|
221
|
+
class ScrollListener {
|
|
222
|
+
constructor(el) {
|
|
223
|
+
this.el = el;
|
|
224
|
+
this.emitter = new internal_cjs.Emitter();
|
|
225
|
+
this.isScrolling = false;
|
|
226
|
+
this.isTouching = false; // user currently has finger down?
|
|
227
|
+
this.isRecentlyWheeled = false;
|
|
228
|
+
this.isRecentlyScrolled = false;
|
|
229
|
+
this.wheelWaiter = new internal_cjs.DelayedRunner(this._handleWheelWaited.bind(this));
|
|
230
|
+
this.scrollWaiter = new internal_cjs.DelayedRunner(this._handleScrollWaited.bind(this));
|
|
231
|
+
// Handlers
|
|
232
|
+
// ----------------------------------------------------------------------------------------------
|
|
233
|
+
this.handleScroll = () => {
|
|
234
|
+
this.startScroll();
|
|
235
|
+
this.emitter.trigger('scroll', this.isRecentlyWheeled, this.isTouching);
|
|
236
|
+
this.isRecentlyScrolled = true;
|
|
237
|
+
this.scrollWaiter.request(500);
|
|
238
|
+
};
|
|
239
|
+
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
240
|
+
this.handleWheel = () => {
|
|
241
|
+
this.isRecentlyWheeled = true;
|
|
242
|
+
this.wheelWaiter.request(500);
|
|
243
|
+
};
|
|
244
|
+
// will fire *before* the scroll event is fired (might not cause a scroll)
|
|
245
|
+
this.handleTouchStart = () => {
|
|
246
|
+
this.isTouching = true;
|
|
247
|
+
};
|
|
248
|
+
this.handleTouchEnd = () => {
|
|
249
|
+
this.isTouching = false;
|
|
250
|
+
// if the user ended their touch, and the scroll area wasn't moving,
|
|
251
|
+
// we consider this to be the end of the scroll.
|
|
252
|
+
if (!this.isRecentlyScrolled) {
|
|
253
|
+
this.endScroll(); // won't fire if already ended
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
el.addEventListener('scroll', this.handleScroll);
|
|
257
|
+
el.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
258
|
+
el.addEventListener('touchend', this.handleTouchEnd);
|
|
259
|
+
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
260
|
+
el.addEventListener(eventName, this.handleWheel);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
destroy() {
|
|
264
|
+
let { el } = this;
|
|
265
|
+
el.removeEventListener('scroll', this.handleScroll);
|
|
266
|
+
el.removeEventListener('touchstart', this.handleTouchStart, { passive: true });
|
|
267
|
+
el.removeEventListener('touchend', this.handleTouchEnd);
|
|
268
|
+
for (let eventName of WHEEL_EVENT_NAMES) {
|
|
269
|
+
el.removeEventListener(eventName, this.handleWheel);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// Start / Stop
|
|
273
|
+
// ----------------------------------------------------------------------------------------------
|
|
274
|
+
startScroll() {
|
|
275
|
+
if (!this.isScrolling) {
|
|
276
|
+
this.isScrolling = true;
|
|
277
|
+
this.emitter.trigger('scrollStart', this.isRecentlyWheeled, this.isTouching);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
endScroll() {
|
|
281
|
+
if (this.isScrolling) {
|
|
282
|
+
this.emitter.trigger('scrollEnd');
|
|
283
|
+
this.isScrolling = false;
|
|
284
|
+
this.isRecentlyScrolled = true;
|
|
285
|
+
this.isRecentlyWheeled = false;
|
|
286
|
+
this.scrollWaiter.clear();
|
|
287
|
+
this.wheelWaiter.clear();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
_handleScrollWaited() {
|
|
291
|
+
this.isRecentlyScrolled = false;
|
|
292
|
+
// only end the scroll if not currently touching.
|
|
293
|
+
// if touching, the scrolling will end later, on touchend.
|
|
294
|
+
if (!this.isTouching) {
|
|
295
|
+
this.endScroll(); // won't fire if already ended
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
_handleWheelWaited() {
|
|
299
|
+
this.isRecentlyWheeled = false;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
404
303
|
class ScrollSyncer {
|
|
405
304
|
constructor(isVertical, scrollEls) {
|
|
406
305
|
this.isVertical = isVertical;
|
|
@@ -471,20 +370,20 @@ class ScrollSyncer {
|
|
|
471
370
|
}
|
|
472
371
|
}
|
|
473
372
|
|
|
373
|
+
internal_cjs.config.SCROLLGRID_RESIZE_INTERVAL = 500;
|
|
474
374
|
/*
|
|
475
375
|
TODO: make <ScrollGridSection> subcomponent
|
|
476
376
|
NOTE: doesn't support collapsibleWidth (which is sortof a hack anyway)
|
|
477
377
|
*/
|
|
478
|
-
class ScrollGrid extends
|
|
378
|
+
class ScrollGrid extends internal_cjs.BaseComponent {
|
|
479
379
|
constructor() {
|
|
480
380
|
super(...arguments);
|
|
481
|
-
this.compileColGroupStats =
|
|
482
|
-
this.renderMicroColGroups =
|
|
483
|
-
this.clippedScrollerRefs = new
|
|
381
|
+
this.compileColGroupStats = internal_cjs.memoizeArraylike(compileColGroupStat, isColGroupStatsEqual);
|
|
382
|
+
this.renderMicroColGroups = internal_cjs.memoizeArraylike(internal_cjs.renderMicroColGroup); // yucky to memoize VNodes, but much more efficient for consumers
|
|
383
|
+
this.clippedScrollerRefs = new internal_cjs.RefMap();
|
|
484
384
|
// doesn't hold non-scrolling els used just for padding
|
|
485
|
-
this.scrollerElRefs = new
|
|
486
|
-
this.chunkElRefs = new
|
|
487
|
-
this.stickyScrollings = [];
|
|
385
|
+
this.scrollerElRefs = new internal_cjs.RefMap(this._handleScrollerEl.bind(this));
|
|
386
|
+
this.chunkElRefs = new internal_cjs.RefMap(this._handleChunkEl.bind(this));
|
|
488
387
|
this.scrollSyncersBySection = {};
|
|
489
388
|
this.scrollSyncersByColumn = {};
|
|
490
389
|
// for row-height-syncing
|
|
@@ -544,7 +443,7 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
544
443
|
let { shrinkWidths } = state;
|
|
545
444
|
let colGroupStats = this.compileColGroupStats(props.colGroups.map((colGroup) => [colGroup]));
|
|
546
445
|
let microColGroupNodes = this.renderMicroColGroups(colGroupStats.map((stat, i) => [stat.cols, shrinkWidths[i]]));
|
|
547
|
-
let classNames =
|
|
446
|
+
let classNames = internal_cjs.getScrollGridClassNames(props.liquid, context);
|
|
548
447
|
this.getDims();
|
|
549
448
|
// TODO: make DRY
|
|
550
449
|
let sectionConfigs = props.sections;
|
|
@@ -566,39 +465,39 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
566
465
|
footSectionNodes.push(this.renderSection(currentConfig, configI, colGroupStats, microColGroupNodes, state.sectionRowMaxHeights, true));
|
|
567
466
|
configI += 1;
|
|
568
467
|
}
|
|
569
|
-
const isBuggy = !
|
|
468
|
+
const isBuggy = !internal_cjs.getCanVGrowWithinCell(); // see NOTE in SimpleScrollGrid
|
|
570
469
|
const roleAttrs = { role: 'rowgroup' };
|
|
571
|
-
return
|
|
470
|
+
return preact_cjs.createElement('table', {
|
|
572
471
|
ref: props.elRef,
|
|
573
472
|
role: 'grid',
|
|
574
473
|
className: classNames.join(' '),
|
|
575
|
-
}, renderMacroColGroup(colGroupStats, shrinkWidths), Boolean(!isBuggy && headSectionNodes.length) &&
|
|
474
|
+
}, renderMacroColGroup(colGroupStats, shrinkWidths), Boolean(!isBuggy && headSectionNodes.length) && preact_cjs.createElement('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && preact_cjs.createElement('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && preact_cjs.createElement('tfoot', roleAttrs, ...footSectionNodes), isBuggy && preact_cjs.createElement('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
|
|
576
475
|
}
|
|
577
476
|
renderSection(sectionConfig, sectionIndex, colGroupStats, microColGroupNodes, sectionRowMaxHeights, isHeader) {
|
|
578
477
|
if ('outerContent' in sectionConfig) {
|
|
579
|
-
return (
|
|
478
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, { key: sectionConfig.key }, sectionConfig.outerContent));
|
|
580
479
|
}
|
|
581
|
-
return (
|
|
480
|
+
return (preact_cjs.createElement("tr", { key: sectionConfig.key, role: "presentation", className: internal_cjs.getSectionClassNames(sectionConfig, this.props.liquid).join(' ') }, sectionConfig.chunks.map((chunkConfig, i) => this.renderChunk(sectionConfig, sectionIndex, colGroupStats[i], microColGroupNodes[i], chunkConfig, i, (sectionRowMaxHeights[sectionIndex] || [])[i] || [], isHeader))));
|
|
582
481
|
}
|
|
583
482
|
renderChunk(sectionConfig, sectionIndex, colGroupStat, microColGroupNode, chunkConfig, chunkIndex, rowHeights, isHeader) {
|
|
584
483
|
if ('outerContent' in chunkConfig) {
|
|
585
|
-
return (
|
|
484
|
+
return (preact_cjs.createElement(preact_cjs.Fragment, { key: chunkConfig.key }, chunkConfig.outerContent));
|
|
586
485
|
}
|
|
587
486
|
let { state } = this;
|
|
588
487
|
let { scrollerClientWidths, scrollerClientHeights } = state;
|
|
589
488
|
let [sectionCnt, chunksPerSection] = this.getDims();
|
|
590
489
|
let index = sectionIndex * chunksPerSection + chunkIndex;
|
|
591
|
-
let sideScrollIndex = (!this.context.isRtl ||
|
|
490
|
+
let sideScrollIndex = (!this.context.isRtl || internal_cjs.getIsRtlScrollbarOnLeft()) ? chunksPerSection - 1 : 0;
|
|
592
491
|
let isVScrollSide = chunkIndex === sideScrollIndex;
|
|
593
492
|
let isLastSection = sectionIndex === sectionCnt - 1;
|
|
594
493
|
let forceXScrollbars = isLastSection && state.forceXScrollbars; // NOOOO can result in `null`
|
|
595
494
|
let forceYScrollbars = isVScrollSide && state.forceYScrollbars; // NOOOO can result in `null`
|
|
596
495
|
let allowXScrolling = colGroupStat && colGroupStat.allowXScrolling; // rename?
|
|
597
|
-
let allowYScrolling =
|
|
598
|
-
let chunkVGrow =
|
|
496
|
+
let allowYScrolling = internal_cjs.getAllowYScrolling(this.props, sectionConfig); // rename? do in section func?
|
|
497
|
+
let chunkVGrow = internal_cjs.getSectionHasLiquidHeight(this.props, sectionConfig); // do in section func?
|
|
599
498
|
let expandRows = sectionConfig.expandRows && chunkVGrow;
|
|
600
499
|
let tableMinWidth = (colGroupStat && colGroupStat.totalColMinWidth) || '';
|
|
601
|
-
let content =
|
|
500
|
+
let content = internal_cjs.renderChunkContent(sectionConfig, chunkConfig, {
|
|
602
501
|
tableColGroupNode: microColGroupNode,
|
|
603
502
|
tableMinWidth,
|
|
604
503
|
clientWidth: scrollerClientWidths[index] !== undefined ? scrollerClientWidths[index] : null,
|
|
@@ -616,17 +515,17 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
616
515
|
(isVScrollSide ? 'auto' : 'scroll-hidden');
|
|
617
516
|
// it *could* be possible to reduce DOM wrappers by only doing a ClippedScroller when allowXScrolling or allowYScrolling,
|
|
618
517
|
// but if these values were to change, the inner components would be unmounted/remounted because of the parent change.
|
|
619
|
-
content = (
|
|
620
|
-
return
|
|
518
|
+
content = (preact_cjs.createElement(ClippedScroller, { ref: this.clippedScrollerRefs.createRef(index), scrollerElRef: this.scrollerElRefs.createRef(index), overflowX: overflowX, overflowY: overflowY, liquid: chunkVGrow, maxHeight: sectionConfig.maxHeight }, content));
|
|
519
|
+
return preact_cjs.createElement(isHeader ? 'th' : 'td', {
|
|
621
520
|
key: chunkConfig.key,
|
|
622
521
|
ref: this.chunkElRefs.createRef(index),
|
|
623
522
|
role: 'presentation',
|
|
624
523
|
}, content);
|
|
625
524
|
}
|
|
626
525
|
componentDidMount() {
|
|
627
|
-
this.getStickyScrolling =
|
|
628
|
-
this.getScrollSyncersBySection =
|
|
629
|
-
this.getScrollSyncersByColumn =
|
|
526
|
+
this.getStickyScrolling = internal_cjs.memoizeArraylike(initStickyScrolling);
|
|
527
|
+
this.getScrollSyncersBySection = internal_cjs.memoizeHashlike(initScrollSyncer.bind(this, true), null, destroyScrollSyncer);
|
|
528
|
+
this.getScrollSyncersByColumn = internal_cjs.memoizeHashlike(initScrollSyncer.bind(this, false), null, destroyScrollSyncer);
|
|
630
529
|
this.updateScrollSyncers();
|
|
631
530
|
this.handleSizing(false);
|
|
632
531
|
this.context.addResizeHandler(this.handleSizing);
|
|
@@ -638,13 +537,12 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
638
537
|
}
|
|
639
538
|
componentWillUnmount() {
|
|
640
539
|
this.context.removeResizeHandler(this.handleSizing);
|
|
641
|
-
this.destroyStickyScrolling();
|
|
642
540
|
this.destroyScrollSyncers();
|
|
643
541
|
}
|
|
644
542
|
allowSizing() {
|
|
645
543
|
let now = new Date();
|
|
646
544
|
if (!this.lastSizingDate ||
|
|
647
|
-
now.valueOf() > this.lastSizingDate.valueOf() +
|
|
545
|
+
now.valueOf() > this.lastSizingDate.valueOf() + internal_cjs.config.SCROLLGRID_RESIZE_INTERVAL) {
|
|
648
546
|
this.lastSizingDate = now;
|
|
649
547
|
this.recentSizingCnt = 0;
|
|
650
548
|
return true;
|
|
@@ -659,7 +557,7 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
659
557
|
colGroupStats.forEach((colGroupStat, i) => {
|
|
660
558
|
if (colGroupStat.hasShrinkCol) {
|
|
661
559
|
let chunkEls = this.chunkElRefs.collect(i, cnt, chunksPerSection); // in one col
|
|
662
|
-
shrinkWidths[i] =
|
|
560
|
+
shrinkWidths[i] = internal_cjs.computeShrinkWidth(chunkEls);
|
|
663
561
|
}
|
|
664
562
|
});
|
|
665
563
|
return shrinkWidths;
|
|
@@ -680,7 +578,7 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
680
578
|
let rowHeights = [];
|
|
681
579
|
let chunkEl = this.chunkElRefs.currentMap[index];
|
|
682
580
|
if (chunkEl) {
|
|
683
|
-
rowHeights =
|
|
581
|
+
rowHeights = internal_cjs.findElements(chunkEl, '.fc-scrollgrid-sync-table tr').map((rowEl) => {
|
|
684
582
|
let max = getRowInnerMaxHeight(rowEl);
|
|
685
583
|
newHeightMap.set(rowEl, max);
|
|
686
584
|
return max;
|
|
@@ -751,9 +649,9 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
751
649
|
return sectionRowMaxHeights;
|
|
752
650
|
}
|
|
753
651
|
computeScrollerDims() {
|
|
754
|
-
let scrollbarWidth =
|
|
652
|
+
let scrollbarWidth = internal_cjs.getScrollbarWidths();
|
|
755
653
|
let [sectionCnt, chunksPerSection] = this.getDims();
|
|
756
|
-
let sideScrollI = (!this.context.isRtl ||
|
|
654
|
+
let sideScrollI = (!this.context.isRtl || internal_cjs.getIsRtlScrollbarOnLeft()) ? chunksPerSection - 1 : 0;
|
|
757
655
|
let lastSectionI = sectionCnt - 1;
|
|
758
656
|
let currentScrollers = this.clippedScrollerRefs.currentMap;
|
|
759
657
|
let scrollerEls = this.scrollerElRefs.currentMap;
|
|
@@ -798,12 +696,8 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
798
696
|
updateStickyScrolling() {
|
|
799
697
|
let { isRtl } = this.context;
|
|
800
698
|
let argsByKey = this.scrollerElRefs.getAll().map((scrollEl) => [scrollEl, isRtl]);
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
this.stickyScrollings = stickyScrollings;
|
|
804
|
-
}
|
|
805
|
-
destroyStickyScrolling() {
|
|
806
|
-
this.stickyScrollings.forEach(destroyStickyScrolling);
|
|
699
|
+
this.getStickyScrolling(argsByKey)
|
|
700
|
+
.forEach((stickyScrolling) => stickyScrolling.updateSize());
|
|
807
701
|
}
|
|
808
702
|
updateScrollSyncers() {
|
|
809
703
|
let [sectionCnt, chunksPerSection] = this.getDims();
|
|
@@ -814,7 +708,7 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
814
708
|
for (let sectionI = 0; sectionI < sectionCnt; sectionI += 1) {
|
|
815
709
|
let startIndex = sectionI * chunksPerSection;
|
|
816
710
|
let endIndex = startIndex + chunksPerSection;
|
|
817
|
-
scrollElsBySection[sectionI] =
|
|
711
|
+
scrollElsBySection[sectionI] = internal_cjs.collectFromHash(scrollElMap, startIndex, endIndex, 1); // use the filtered
|
|
818
712
|
}
|
|
819
713
|
for (let col = 0; col < chunksPerSection; col += 1) {
|
|
820
714
|
scrollElsByColumn[col] = this.scrollerElRefs.collect(col, cnt, chunksPerSection); // DON'T use the filtered
|
|
@@ -823,8 +717,8 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
823
717
|
this.scrollSyncersByColumn = this.getScrollSyncersByColumn(scrollElsByColumn);
|
|
824
718
|
}
|
|
825
719
|
destroyScrollSyncers() {
|
|
826
|
-
|
|
827
|
-
|
|
720
|
+
internal_cjs.mapHash(this.scrollSyncersBySection, destroyScrollSyncer);
|
|
721
|
+
internal_cjs.mapHash(this.scrollSyncersByColumn, destroyScrollSyncer);
|
|
828
722
|
}
|
|
829
723
|
getChunkConfigByIndex(index) {
|
|
830
724
|
let chunksPerSection = this.getDims()[1];
|
|
@@ -848,13 +742,13 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
848
742
|
_handleChunkEl(chunkEl, key) {
|
|
849
743
|
let chunkConfig = this.getChunkConfigByIndex(parseInt(key, 10));
|
|
850
744
|
if (chunkConfig) { // null if section disappeared. bad, b/c won't null-set the elRef
|
|
851
|
-
|
|
745
|
+
internal_cjs.setRef(chunkConfig.elRef, chunkEl);
|
|
852
746
|
}
|
|
853
747
|
}
|
|
854
748
|
_handleScrollerEl(scrollerEl, key) {
|
|
855
749
|
let chunkConfig = this.getChunkConfigByIndex(parseInt(key, 10));
|
|
856
750
|
if (chunkConfig) { // null if section disappeared. bad, b/c won't null-set the elRef
|
|
857
|
-
|
|
751
|
+
internal_cjs.setRef(chunkConfig.scrollerElRef, scrollerEl);
|
|
858
752
|
}
|
|
859
753
|
}
|
|
860
754
|
getDims() {
|
|
@@ -864,9 +758,9 @@ class ScrollGrid extends common.BaseComponent {
|
|
|
864
758
|
}
|
|
865
759
|
}
|
|
866
760
|
ScrollGrid.addStateEquality({
|
|
867
|
-
shrinkWidths:
|
|
868
|
-
scrollerClientWidths:
|
|
869
|
-
scrollerClientHeights:
|
|
761
|
+
shrinkWidths: internal_cjs.isArraysEqual,
|
|
762
|
+
scrollerClientWidths: internal_cjs.isPropsEqual,
|
|
763
|
+
scrollerClientHeights: internal_cjs.isPropsEqual,
|
|
870
764
|
});
|
|
871
765
|
function sumNumbers(numbers) {
|
|
872
766
|
let sum = 0;
|
|
@@ -876,7 +770,7 @@ function sumNumbers(numbers) {
|
|
|
876
770
|
return sum;
|
|
877
771
|
}
|
|
878
772
|
function getRowInnerMaxHeight(rowEl) {
|
|
879
|
-
let innerHeights =
|
|
773
|
+
let innerHeights = internal_cjs.findElements(rowEl, '.fc-scrollgrid-sync-inner').map(getElHeight);
|
|
880
774
|
if (innerHeights.length) {
|
|
881
775
|
return Math.max(...innerHeights);
|
|
882
776
|
}
|
|
@@ -889,17 +783,17 @@ function renderMacroColGroup(colGroupStats, shrinkWidths) {
|
|
|
889
783
|
let children = colGroupStats.map((colGroupStat, i) => {
|
|
890
784
|
let width = colGroupStat.width;
|
|
891
785
|
if (width === 'shrink') {
|
|
892
|
-
width = colGroupStat.totalColWidth +
|
|
786
|
+
width = colGroupStat.totalColWidth + internal_cjs.sanitizeShrinkWidth(shrinkWidths[i]) + 1; // +1 for border :(
|
|
893
787
|
}
|
|
894
788
|
return ( // eslint-disable-next-line react/jsx-key
|
|
895
|
-
|
|
789
|
+
preact_cjs.createElement("col", { style: { width } }));
|
|
896
790
|
});
|
|
897
|
-
return
|
|
791
|
+
return preact_cjs.createElement('colgroup', {}, ...children);
|
|
898
792
|
}
|
|
899
793
|
function compileColGroupStat(colGroupConfig) {
|
|
900
794
|
let totalColWidth = sumColProp(colGroupConfig.cols, 'width'); // excludes "shrink"
|
|
901
795
|
let totalColMinWidth = sumColProp(colGroupConfig.cols, 'minWidth');
|
|
902
|
-
let hasShrinkCol =
|
|
796
|
+
let hasShrinkCol = internal_cjs.hasShrinkWidth(colGroupConfig.cols);
|
|
903
797
|
let allowXScrolling = colGroupConfig.width !== 'shrink' && Boolean(totalColWidth || totalColMinWidth || hasShrinkCol);
|
|
904
798
|
return {
|
|
905
799
|
hasShrinkCol,
|
|
@@ -921,10 +815,10 @@ function sumColProp(cols, propName) {
|
|
|
921
815
|
return total;
|
|
922
816
|
}
|
|
923
817
|
const COL_GROUP_STAT_EQUALITY = {
|
|
924
|
-
cols:
|
|
818
|
+
cols: internal_cjs.isColPropsEqual,
|
|
925
819
|
};
|
|
926
820
|
function isColGroupStatsEqual(stat0, stat1) {
|
|
927
|
-
return
|
|
821
|
+
return internal_cjs.compareObjs(stat0, stat1, COL_GROUP_STAT_EQUALITY);
|
|
928
822
|
}
|
|
929
823
|
// for memoizers...
|
|
930
824
|
function initScrollSyncer(isVertical, ...scrollEls) {
|
|
@@ -936,18 +830,5 @@ function destroyScrollSyncer(scrollSyncer) {
|
|
|
936
830
|
function initStickyScrolling(scrollEl, isRtl) {
|
|
937
831
|
return new StickyScrolling(scrollEl, isRtl);
|
|
938
832
|
}
|
|
939
|
-
function destroyStickyScrolling(stickyScrolling) {
|
|
940
|
-
stickyScrolling.destroy();
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
var main = common.createPlugin({
|
|
944
|
-
deps: [
|
|
945
|
-
premiumCommonPlugin__default['default'],
|
|
946
|
-
],
|
|
947
|
-
scrollGridImpl: ScrollGrid,
|
|
948
|
-
});
|
|
949
|
-
common.config.SCROLLGRID_RESIZE_INTERVAL = 500;
|
|
950
833
|
|
|
951
834
|
exports.ScrollGrid = ScrollGrid;
|
|
952
|
-
exports.default = main;
|
|
953
|
-
exports.setScrollFromLeftEdge = setScrollFromLeftEdge;
|