@fastkit/scroller 0.14.5 → 0.16.0-next.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/scroller.mjs CHANGED
@@ -1,1363 +1,1357 @@
1
- import { EV } from '@fastkit/ev';
2
- import { visibilityManager } from '@fastkit/visibility';
3
- import { IN_WINDOW, removeUndef } from '@fastkit/helpers';
4
- import { TinyLogger } from '@fastkit/tiny-logger';
5
- import BezierEasing from 'bezier-easing';
1
+ import { EV } from "@fastkit/ev";
2
+ import { visibilityManager } from "@fastkit/visibility";
3
+ import { IN_WINDOW, removeUndef } from "@fastkit/helpers";
4
+ import { TinyLogger } from "@fastkit/tiny-logger";
5
+ import BezierEasing from "bezier-easing";
6
6
 
7
- // src/util.ts
7
+ //#region src/util.ts
8
8
  function isDocumentElement(el) {
9
- return el.constructor === HTMLHtmlElement;
9
+ return el.constructor === HTMLHtmlElement;
10
10
  }
11
- function isBodyElement(el) {
12
- return el.constructor === HTMLBodyElement;
11
+ function isBodyElement$1(el) {
12
+ return el.constructor === HTMLBodyElement;
13
13
  }
14
- var logger = new TinyLogger("scroller");
15
14
 
16
- // src/prevent-scroll.ts
17
- var SCROLLABLE_KEY_CODES = [32, 33, 34, 35, 36, 37, 38, 39, 40];
18
- var eventListenerOptions = {
19
- passive: false
20
- };
21
- var handleWheel = (e) => {
22
- e.preventDefault();
15
+ //#endregion
16
+ //#region src/logger.ts
17
+ const logger = new TinyLogger("scroller");
18
+
19
+ //#endregion
20
+ //#region src/prevent-scroll.ts
21
+ const SCROLLABLE_KEY_CODES = [
22
+ 32,
23
+ 33,
24
+ 34,
25
+ 35,
26
+ 36,
27
+ 37,
28
+ 38,
29
+ 39,
30
+ 40
31
+ ];
32
+ const eventListenerOptions = { passive: false };
33
+ const handleWheel = (e) => {
34
+ e.preventDefault();
23
35
  };
24
- var handleScroll = (e) => {
25
- const el = e.target;
26
- if (el && el.__ps_ctx__) {
27
- el.scrollTo(el.__ps_ctx__.lockPosition.x, el.__ps_ctx__.lockPosition.y);
28
- }
36
+ const handleScroll = (e) => {
37
+ const el = e.target;
38
+ if (el && el.__ps_ctx__) el.scrollTo(el.__ps_ctx__.lockPosition.x, el.__ps_ctx__.lockPosition.y);
29
39
  };
30
- var handleKeydown = (e) => {
31
- if (e.target && ["INPUT", "TEXTAREA"].includes(e.target.tagName)) {
32
- return;
33
- }
34
- if (SCROLLABLE_KEY_CODES.includes(e.which)) {
35
- e.preventDefault();
36
- }
40
+ const handleKeydown = (e) => {
41
+ if (e.target && ["INPUT", "TEXTAREA"].includes(e.target.tagName)) return;
42
+ if (SCROLLABLE_KEY_CODES.includes(e.which)) e.preventDefault();
37
43
  };
38
44
  function enableScroll(el) {
39
- const _el = el;
40
- if (!_el.__ps_ctx__) return;
41
- const { options } = _el.__ps_ctx__;
42
- _el.removeEventListener("wheel", handleWheel, eventListenerOptions);
43
- _el.removeEventListener("scroll", handleScroll, eventListenerOptions);
44
- _el.removeEventListener("keydown", handleKeydown);
45
- if (options.hideScrollbar) {
46
- _el.style.overflow = _el.__ps_ctx__.overflowOrigin;
47
- }
48
- delete _el.__ps_ctx__;
45
+ const _el = el;
46
+ if (!_el.__ps_ctx__) return;
47
+ const { options } = _el.__ps_ctx__;
48
+ _el.removeEventListener("wheel", handleWheel, eventListenerOptions);
49
+ _el.removeEventListener("scroll", handleScroll, eventListenerOptions);
50
+ _el.removeEventListener("keydown", handleKeydown);
51
+ if (options.hideScrollbar) _el.style.overflow = _el.__ps_ctx__.overflowOrigin;
52
+ delete _el.__ps_ctx__;
49
53
  }
50
54
  function disableScroll(el, opts = {}) {
51
- const { hideScrollbar = false } = opts;
52
- const _el = el;
53
- if (_el.__ps_ctx__) return;
54
- const options = {
55
- hideScrollbar
56
- };
57
- _el.__ps_ctx__ = {
58
- options,
59
- el: _el,
60
- overflowOrigin: _el.style.overflow,
61
- lockPosition: {
62
- x: _el.scrollLeft || _el.scrollX,
63
- y: _el.scrollTop || _el.scrollY
64
- }
65
- };
66
- if (options.hideScrollbar) {
67
- _el.style.overflow = "hidden";
68
- }
69
- _el.addEventListener("wheel", handleWheel, eventListenerOptions);
70
- _el.addEventListener("scroll", handleScroll, eventListenerOptions);
71
- _el.addEventListener("keydown", handleKeydown);
55
+ const { hideScrollbar = false } = opts;
56
+ const _el = el;
57
+ if (_el.__ps_ctx__) return;
58
+ const options = { hideScrollbar };
59
+ _el.__ps_ctx__ = {
60
+ options,
61
+ el: _el,
62
+ overflowOrigin: _el.style.overflow,
63
+ lockPosition: {
64
+ x: _el.scrollLeft || _el.scrollX,
65
+ y: _el.scrollTop || _el.scrollY
66
+ }
67
+ };
68
+ if (options.hideScrollbar) _el.style.overflow = "hidden";
69
+ _el.addEventListener("wheel", handleWheel, eventListenerOptions);
70
+ _el.addEventListener("scroll", handleScroll, eventListenerOptions);
71
+ _el.addEventListener("keydown", handleKeydown);
72
72
  }
73
73
 
74
- // src/scroll/schemes.ts
75
- var defaultBaseSettings = {
76
- duration: 500,
77
- easing: "ease",
78
- cancelable: true
74
+ //#endregion
75
+ //#region src/scroll/schemes.ts
76
+ const defaultBaseSettings = {
77
+ duration: 500,
78
+ easing: "ease",
79
+ cancelable: true
79
80
  };
80
- var defaultSettings = {
81
- get container() {
82
- return document.scrollingElement;
83
- },
84
- ...defaultBaseSettings
81
+ const defaultSettings = {
82
+ get container() {
83
+ return document.scrollingElement;
84
+ },
85
+ ...defaultBaseSettings
85
86
  };
86
87
 
87
- // src/scroll/easings.ts
88
- var easings = {
89
- ease: [0.25, 0.1, 0.25, 1],
90
- linear: [0, 0, 1, 1],
91
- "ease-in": [0.42, 0, 1, 1],
92
- "ease-out": [0, 0, 0.58, 1],
93
- "ease-in-out": [0.42, 0, 0.58, 1]
88
+ //#endregion
89
+ //#region src/scroll/easings.ts
90
+ const easings = {
91
+ ease: [
92
+ .25,
93
+ .1,
94
+ .25,
95
+ 1
96
+ ],
97
+ linear: [
98
+ 0,
99
+ 0,
100
+ 1,
101
+ 1
102
+ ],
103
+ "ease-in": [
104
+ .42,
105
+ 0,
106
+ 1,
107
+ 1
108
+ ],
109
+ "ease-out": [
110
+ 0,
111
+ 0,
112
+ .58,
113
+ 1
114
+ ],
115
+ "ease-in-out": [
116
+ .42,
117
+ 0,
118
+ .58,
119
+ 1
120
+ ]
94
121
  };
95
122
  var easings_default = easings;
96
123
 
97
- // src/scroll/util.ts
98
- function isBodyElement2(el) {
99
- return el.tagName.toLowerCase() === "body";
124
+ //#endregion
125
+ //#region src/scroll/util.ts
126
+ function isBodyElement(el) {
127
+ return el.tagName.toLowerCase() === "body";
100
128
  }
101
129
  function getContainerDimension(el) {
102
- if (isBodyElement2(el)) {
103
- const documentElement = document.documentElement;
104
- return {
105
- // width: window.innerWidth,
106
- // height: window.innerHeight,
107
- width: documentElement.clientWidth,
108
- height: documentElement.clientWidth
109
- };
110
- }
111
- return {
112
- width: el.clientWidth,
113
- height: el.clientHeight
114
- };
130
+ if (isBodyElement(el)) {
131
+ const documentElement = document.documentElement;
132
+ return {
133
+ width: documentElement.clientWidth,
134
+ height: documentElement.clientWidth
135
+ };
136
+ }
137
+ return {
138
+ width: el.clientWidth,
139
+ height: el.clientHeight
140
+ };
115
141
  }
116
142
  function $(selectorOrElement) {
117
- if (typeof selectorOrElement !== "string")
118
- return selectorOrElement;
119
- return document.querySelector(selectorOrElement);
143
+ if (typeof selectorOrElement !== "string") return selectorOrElement;
144
+ return document.querySelector(selectorOrElement);
120
145
  }
121
146
  function cumulativeOffset(element) {
122
- let top = 0;
123
- let left = 0;
124
- let el = element;
125
- while (el) {
126
- top += el.offsetTop || 0;
127
- left += el.offsetLeft || 0;
128
- el = el.offsetParent;
129
- }
130
- return {
131
- top,
132
- left
133
- };
147
+ let top = 0;
148
+ let left = 0;
149
+ let el = element;
150
+ while (el) {
151
+ top += el.offsetTop || 0;
152
+ left += el.offsetLeft || 0;
153
+ el = el.offsetParent;
154
+ }
155
+ return {
156
+ top,
157
+ left
158
+ };
134
159
  }
135
160
  function on(element, events, handler, opts = { passive: false }) {
136
- if (!Array.isArray(events)) events = [events];
137
- for (let i = 0; i < events.length; i++) {
138
- element.addEventListener(events[i], handler, opts);
139
- }
161
+ if (!Array.isArray(events)) events = [events];
162
+ for (let i = 0; i < events.length; i++) element.addEventListener(events[i], handler, opts);
140
163
  }
141
164
  function off(element, events, handler) {
142
- if (!Array.isArray(events)) events = [events];
143
- for (let i = 0; i < events.length; i++) {
144
- element.removeEventListener(events[i], handler);
145
- }
165
+ if (!Array.isArray(events)) events = [events];
166
+ for (let i = 0; i < events.length; i++) element.removeEventListener(events[i], handler);
146
167
  }
147
168
  function error(message) {
148
- return new Error(`[scroll] ${message}`);
169
+ return /* @__PURE__ */ new Error(`[scroll] ${message}`);
149
170
  }
150
171
 
151
- // src/scroll/scroll-by-internal.ts
152
- var abortEvents = [
153
- "mousedown",
154
- "wheel",
155
- "DOMMouseScroll",
156
- "mousewheel",
157
- "keyup",
158
- "touchmove"
172
+ //#endregion
173
+ //#region src/scroll/scroll-by-internal.ts
174
+ const abortEvents = [
175
+ "mousedown",
176
+ "wheel",
177
+ "DOMMouseScroll",
178
+ "mousewheel",
179
+ "keyup",
180
+ "touchmove"
159
181
  ];
160
182
  function scroll(diffX, diffY, options = {}, _computedValues) {
161
- let $container;
162
- let initialX;
163
- let initialY;
164
- let targetX;
165
- let targetY;
166
- const _options = { ...defaultSettings, ...removeUndef(options) };
167
- const {
168
- container,
169
- duration,
170
- easing,
171
- cancelable,
172
- onProgress,
173
- onCancel,
174
- onDone
175
- } = _options;
176
- const x = diffX !== 0;
177
- const y = diffY !== 0;
178
- if (_computedValues) {
179
- $container = _computedValues.$container;
180
- initialX = _computedValues.initialX;
181
- initialY = _computedValues.initialY;
182
- targetX = _computedValues.targetX;
183
- targetY = _computedValues.targetY;
184
- } else {
185
- $container = $(container);
186
- if (!$container) throw error(`missing container ${container}`);
187
- initialX = $container.scrollLeft;
188
- initialY = $container.scrollTop;
189
- targetX = initialX + diffX;
190
- targetY = initialY + diffY;
191
- }
192
- const { scrollWidth, scrollHeight } = $container;
193
- const { width, height } = getContainerDimension($container);
194
- const overflowX = targetX + width - scrollWidth;
195
- const overflowY = targetY + height - scrollHeight;
196
- if (overflowX > 0) {
197
- diffX -= overflowX;
198
- targetX -= overflowX;
199
- }
200
- if (overflowY > 0) {
201
- diffY -= overflowY;
202
- targetY -= overflowY;
203
- }
204
- let doneResolver;
205
- let timeStart = 0;
206
- let timeElapsed;
207
- const callbackValues = {
208
- container: $container,
209
- progress: 0,
210
- aborted: false,
211
- abortEventSource: null
212
- };
213
- const result = {
214
- cancel: canceller,
215
- promise: new Promise((resolve) => {
216
- doneResolver = resolve;
217
- }),
218
- plans: {
219
- x: diffX,
220
- y: diffY
221
- }
222
- };
223
- if (diffY === 0 && diffX === 0 || !!$container.__ps_ctx__)
224
- return initialAbort();
225
- let easingValues;
226
- if (!easing) {
227
- easingValues = easings_default.ease;
228
- } else if (typeof easing === "string") {
229
- easingValues = easings_default[_options.easing];
230
- } else {
231
- easingValues = easing;
232
- }
233
- const easingFn = BezierEasing.apply(
234
- BezierEasing,
235
- easingValues
236
- );
237
- on($container, abortEvents, abortFn, { passive: true });
238
- window.requestAnimationFrame(step);
239
- return result;
240
- function doneResolve() {
241
- doneResolver();
242
- }
243
- function canceller(e = null, checkCancelable = false) {
244
- if (checkCancelable && !cancelable) return;
245
- off($container, abortEvents, abortFn);
246
- callbackValues.abortEventSource = e;
247
- callbackValues.aborted = true;
248
- onCancel && onCancel(callbackValues);
249
- }
250
- function abortFn(e) {
251
- canceller(e, true);
252
- }
253
- function initialAbort(e = null) {
254
- canceller(e);
255
- doneResolve();
256
- return result;
257
- }
258
- function step(timestamp) {
259
- if (callbackValues.aborted) return done();
260
- if (!timeStart) timeStart = timestamp;
261
- timeElapsed = timestamp - timeStart;
262
- let progress = Math.min(timeElapsed / duration, 1);
263
- progress = easingFn(progress);
264
- callbackValues.progress = progress;
265
- topLeft(initialY + diffY * progress, initialX + diffX * progress);
266
- onProgress && onProgress(callbackValues);
267
- timeElapsed < duration ? window.requestAnimationFrame(step) : done();
268
- }
269
- function topLeft(top, left) {
270
- if (y) $container.scrollTop = top;
271
- if (x) $container.scrollLeft = left;
272
- }
273
- function done() {
274
- if (!callbackValues.aborted) topLeft(targetY, targetX);
275
- timeStart = 0;
276
- off($container, abortEvents, abortFn);
277
- callbackValues.progress = 1;
278
- doneResolve();
279
- if (!callbackValues.aborted && onDone) onDone(callbackValues);
280
- }
183
+ let $container;
184
+ let initialX;
185
+ let initialY;
186
+ let targetX;
187
+ let targetY;
188
+ const _options = {
189
+ ...defaultSettings,
190
+ ...removeUndef(options)
191
+ };
192
+ const { container, duration, easing, cancelable, onProgress, onCancel, onDone } = _options;
193
+ const x = diffX !== 0;
194
+ const y = diffY !== 0;
195
+ if (_computedValues) {
196
+ $container = _computedValues.$container;
197
+ initialX = _computedValues.initialX;
198
+ initialY = _computedValues.initialY;
199
+ targetX = _computedValues.targetX;
200
+ targetY = _computedValues.targetY;
201
+ } else {
202
+ $container = $(container);
203
+ if (!$container) throw error(`missing container ${container}`);
204
+ initialX = $container.scrollLeft;
205
+ initialY = $container.scrollTop;
206
+ targetX = initialX + diffX;
207
+ targetY = initialY + diffY;
208
+ }
209
+ const { scrollWidth, scrollHeight } = $container;
210
+ const { width, height } = getContainerDimension($container);
211
+ const overflowX = targetX + width - scrollWidth;
212
+ const overflowY = targetY + height - scrollHeight;
213
+ if (overflowX > 0) {
214
+ diffX -= overflowX;
215
+ targetX -= overflowX;
216
+ }
217
+ if (overflowY > 0) {
218
+ diffY -= overflowY;
219
+ targetY -= overflowY;
220
+ }
221
+ let doneResolver;
222
+ let timeStart = 0;
223
+ let timeElapsed;
224
+ const callbackValues = {
225
+ container: $container,
226
+ progress: 0,
227
+ aborted: false,
228
+ abortEventSource: null
229
+ };
230
+ const result = {
231
+ cancel: canceller,
232
+ promise: new Promise((resolve) => {
233
+ doneResolver = resolve;
234
+ }),
235
+ plans: {
236
+ x: diffX,
237
+ y: diffY
238
+ }
239
+ };
240
+ if (diffY === 0 && diffX === 0 || !!$container.__ps_ctx__) return initialAbort();
241
+ let easingValues;
242
+ if (!easing) easingValues = easings_default.ease;
243
+ else if (typeof easing === "string") easingValues = easings_default[_options.easing];
244
+ else easingValues = easing;
245
+ const easingFn = BezierEasing.apply(BezierEasing, easingValues);
246
+ on($container, abortEvents, abortFn, { passive: true });
247
+ window.requestAnimationFrame(step);
248
+ return result;
249
+ function doneResolve() {
250
+ doneResolver();
251
+ }
252
+ function canceller(e = null, checkCancelable = false) {
253
+ if (checkCancelable && !cancelable) return;
254
+ off($container, abortEvents, abortFn);
255
+ callbackValues.abortEventSource = e;
256
+ callbackValues.aborted = true;
257
+ onCancel && onCancel(callbackValues);
258
+ }
259
+ function abortFn(e) {
260
+ canceller(e, true);
261
+ }
262
+ function initialAbort(e = null) {
263
+ canceller(e);
264
+ doneResolve();
265
+ return result;
266
+ }
267
+ function step(timestamp) {
268
+ if (callbackValues.aborted) return done();
269
+ if (!timeStart) timeStart = timestamp;
270
+ timeElapsed = timestamp - timeStart;
271
+ let progress = Math.min(timeElapsed / duration, 1);
272
+ progress = easingFn(progress);
273
+ callbackValues.progress = progress;
274
+ topLeft(initialY + diffY * progress, initialX + diffX * progress);
275
+ onProgress && onProgress(callbackValues);
276
+ timeElapsed < duration ? window.requestAnimationFrame(step) : done();
277
+ }
278
+ function topLeft(top, left) {
279
+ if (y) $container.scrollTop = top;
280
+ if (x) $container.scrollLeft = left;
281
+ }
282
+ function done() {
283
+ if (!callbackValues.aborted) topLeft(targetY, targetX);
284
+ timeStart = 0;
285
+ off($container, abortEvents, abortFn);
286
+ callbackValues.progress = 1;
287
+ doneResolve();
288
+ if (!callbackValues.aborted && onDone) onDone(callbackValues);
289
+ }
281
290
  }
282
291
 
283
- // src/scroll/scroll-by.ts
292
+ //#endregion
293
+ //#region src/scroll/scroll-by.ts
294
+ /**
295
+ * 指定の差分だけコンテナをスクロールします。
296
+ * @param diffX - 横軸の移動量(px)です。デフォルトは0です。
297
+ * @param diffY - 縦軸の移動量(px)です。デフォルトは0です。
298
+ * @param options - スクロールオプション
299
+ */
284
300
  function scrollBy(diffX, diffY, options) {
285
- return scroll(diffX, diffY, options);
301
+ return scroll(diffX, diffY, options);
286
302
  }
287
303
 
288
- // src/scroll/scroll-to.ts
304
+ //#endregion
305
+ //#region src/scroll/scroll-to.ts
306
+ /**
307
+ * 任意の位置(px)へコンテナをスクロールします。
308
+ * @param scrollPosition - スクロール先を指定します。x, y 共にオプショナルなるです。未指定の軸は現在のスクロール値のまま保持されます。
309
+ * @param options - スクロールオプション
310
+ */
289
311
  function scrollTo(scrollPosition, options = {}) {
290
- let { x, y } = scrollPosition;
291
- const container = options.container || defaultSettings.container;
292
- const $container = $(container);
293
- if (!$container) throw error(`missing container ${container}`);
294
- const initialY = $container.scrollTop;
295
- const initialX = $container.scrollLeft;
296
- if (x === void 0) x = initialX;
297
- if (y === void 0) y = initialY;
298
- const diffX = x - initialX;
299
- const diffY = y - initialY;
300
- return scroll(diffX, diffY, options, {
301
- $container,
302
- initialX,
303
- initialY,
304
- targetX: x,
305
- targetY: y
306
- });
312
+ let { x, y } = scrollPosition;
313
+ const container = options.container || defaultSettings.container;
314
+ const $container = $(container);
315
+ if (!$container) throw error(`missing container ${container}`);
316
+ const initialY = $container.scrollTop;
317
+ const initialX = $container.scrollLeft;
318
+ if (x === void 0) x = initialX;
319
+ if (y === void 0) y = initialY;
320
+ return scroll(x - initialX, y - initialY, options, {
321
+ $container,
322
+ initialX,
323
+ initialY,
324
+ targetX: x,
325
+ targetY: y
326
+ });
307
327
  }
308
328
 
309
- // src/scroll/scroll-to-element.ts
310
- var scrollToElementSettingsDefaults = {
311
- offset: 0,
312
- x: false,
313
- y: true
329
+ //#endregion
330
+ //#region src/scroll/scroll-to-element.ts
331
+ /**
332
+ * 要素スクロール利用事のデフォルト設定です。
333
+ * {@link ScrollToElementSettings}
334
+ */
335
+ const scrollToElementSettingsDefaults = {
336
+ offset: 0,
337
+ x: false,
338
+ y: true
314
339
  };
340
+ /**
341
+ * 任意の要素の位置へスクロールします。
342
+ * @param target - スクロール先の要素
343
+ * @param options - スクロールオプション
344
+ */
315
345
  function scrollToElement(target, options = {}) {
316
- const _options = { ...scrollToElementSettingsDefaults, ...options };
317
- const { x, y } = _options;
318
- const offsetSource = _options.offset;
319
- const offset = typeof offsetSource === "number" ? { x: offsetSource, y: offsetSource } : offsetSource;
320
- const $target = $(target);
321
- if (!$target) throw error(`missing element ${target}`);
322
- const container = _options.container || defaultSettings.container;
323
- const $container = $(container);
324
- if (!$container) throw error(`missing container ${container}`);
325
- const cumulativeOffsetContainer = cumulativeOffset($container);
326
- const cumulativeOffsetTarget = cumulativeOffset($target);
327
- const initialY = $container.scrollTop;
328
- const initialX = $container.scrollLeft;
329
- const targetY = cumulativeOffsetTarget.top - cumulativeOffsetContainer.top + (offset.y || 0);
330
- const targetX = cumulativeOffsetTarget.left - cumulativeOffsetContainer.left + (offset.x || 0);
331
- const diffX = x ? targetX - initialX : 0;
332
- const diffY = y ? targetY - initialY : 0;
333
- return scroll(diffX, diffY, _options, {
334
- $container,
335
- initialX,
336
- initialY,
337
- targetX,
338
- targetY
339
- });
346
+ const _options = {
347
+ ...scrollToElementSettingsDefaults,
348
+ ...options
349
+ };
350
+ const { x, y } = _options;
351
+ const offsetSource = _options.offset;
352
+ const offset = typeof offsetSource === "number" ? {
353
+ x: offsetSource,
354
+ y: offsetSource
355
+ } : offsetSource;
356
+ const $target = $(target);
357
+ if (!$target) throw error(`missing element ${target}`);
358
+ const container = _options.container || defaultSettings.container;
359
+ const $container = $(container);
360
+ if (!$container) throw error(`missing container ${container}`);
361
+ const cumulativeOffsetContainer = cumulativeOffset($container);
362
+ const cumulativeOffsetTarget = cumulativeOffset($target);
363
+ const initialY = $container.scrollTop;
364
+ const initialX = $container.scrollLeft;
365
+ const targetY = cumulativeOffsetTarget.top - cumulativeOffsetContainer.top + (offset.y || 0);
366
+ const targetX = cumulativeOffsetTarget.left - cumulativeOffsetContainer.left + (offset.x || 0);
367
+ return scroll(x ? targetX - initialX : 0, y ? targetY - initialY : 0, _options, {
368
+ $container,
369
+ initialX,
370
+ initialY,
371
+ targetX,
372
+ targetY
373
+ });
340
374
  }
341
375
 
342
- // src/scroll/scroll-to-side.ts
376
+ //#endregion
377
+ //#region src/scroll/scroll-to-side.ts
378
+ /**
379
+ * コンテナをいずれかの辺までスクロールします。
380
+ * @param targets - 辺を指定します。シングルの文字列、及び配列に対応しています。
381
+ * @param options - スクロールオプション
382
+ */
343
383
  function scrollToSide(targets, options) {
344
- const sides = typeof targets === "string" ? [targets] : targets;
345
- const position = {};
346
- const hasRight = sides.includes("right");
347
- const hasBottom = sides.includes("bottom");
348
- if (sides.includes("top")) {
349
- position.y = 0;
350
- }
351
- if (sides.includes("left")) {
352
- position.x = 0;
353
- }
354
- if (hasRight || hasBottom) {
355
- const container = options && options.container || defaultSettings.container;
356
- const $container = $(container);
357
- if (!$container) throw error(`missing container ${container}`);
358
- if (hasRight) position.x = $container.scrollWidth;
359
- if (hasBottom) position.y = $container.scrollHeight;
360
- }
361
- return scrollTo(position, options);
384
+ const sides = typeof targets === "string" ? [targets] : targets;
385
+ const position = {};
386
+ const hasRight = sides.includes("right");
387
+ const hasBottom = sides.includes("bottom");
388
+ if (sides.includes("top")) position.y = 0;
389
+ if (sides.includes("left")) position.x = 0;
390
+ if (hasRight || hasBottom) {
391
+ const container = options && options.container || defaultSettings.container;
392
+ const $container = $(container);
393
+ if (!$container) throw error(`missing container ${container}`);
394
+ if (hasRight) position.x = $container.scrollWidth;
395
+ if (hasBottom) position.y = $container.scrollHeight;
396
+ }
397
+ return scrollTo(position, options);
362
398
  }
399
+ /**
400
+ * コンテナを上辺までスクロールします。
401
+ * @param options - スクロールオプション
402
+ */
363
403
  function scrollToTop(options) {
364
- return scrollToSide("top", options);
404
+ return scrollToSide("top", options);
365
405
  }
406
+ /**
407
+ * コンテナを右辺までスクロールします。
408
+ * @param options - スクロールオプション
409
+ */
366
410
  function scrollToRight(options) {
367
- return scrollToSide("right", options);
411
+ return scrollToSide("right", options);
368
412
  }
413
+ /**
414
+ * コンテナを下辺までスクロールします。
415
+ * @param options - スクロールオプション
416
+ */
369
417
  function scrollToBottom(options) {
370
- return scrollToSide("bottom", options);
418
+ return scrollToSide("bottom", options);
371
419
  }
420
+ /**
421
+ * コンテナを左辺までスクロールします。
422
+ * @param options - スクロールオプション
423
+ */
372
424
  function scrollToLeft(options) {
373
- return scrollToSide("left", options);
425
+ return scrollToSide("left", options);
374
426
  }
427
+ /**
428
+ * コンテナを左上コーナーまでスクロールします。
429
+ * @param options - スクロールオプション
430
+ */
375
431
  function scrollToLeftTop(options) {
376
- return scrollToSide(["left", "top"], options);
432
+ return scrollToSide(["left", "top"], options);
377
433
  }
434
+ /**
435
+ * コンテナを左下コーナーまでスクロールします。
436
+ * @param options - スクロールオプション
437
+ */
378
438
  function scrollToLeftBottom(options) {
379
- return scrollToSide(["left", "bottom"], options);
439
+ return scrollToSide(["left", "bottom"], options);
380
440
  }
441
+ /**
442
+ * コンテナを右上コーナーまでスクロールします。
443
+ * @param options - スクロールオプション
444
+ */
381
445
  function scrollToRightTop(options) {
382
- return scrollToSide(["right", "top"], options);
446
+ return scrollToSide(["right", "top"], options);
383
447
  }
448
+ /**
449
+ * コンテナを右下コーナーまでスクロールします。
450
+ * @param options - スクロールオプション
451
+ */
384
452
  function scrollToRightBottom(options) {
385
- return scrollToSide(["right", "bottom"], options);
453
+ return scrollToSide(["right", "bottom"], options);
386
454
  }
387
455
 
388
- // src/scroller.ts
389
- var ScrollerState = /* @__PURE__ */ ((ScrollerState2) => {
390
- ScrollerState2["Pending"] = "pending";
391
- ScrollerState2["Ready"] = "ready";
392
- ScrollerState2["Running"] = "running";
393
- ScrollerState2["Destroyed"] = "destroyed";
394
- return ScrollerState2;
395
- })(ScrollerState || {});
396
- var scrollerObservableKeys = [
397
- "state",
398
- "isPending",
399
- "isReady",
400
- "isRunning",
401
- "isDestroyed",
402
- "scrollEnabled",
403
- "containerWidth",
404
- "containerHeight",
405
- "scrollWidth",
406
- "scrollHeight",
407
- "scrollableX",
408
- "scrollableY",
409
- "scrollTop",
410
- "scrollLeft",
411
- "scrollRight",
412
- "scrollBottom",
413
- "lastAxis",
414
- "lastDirection",
415
- "lastYDirection",
416
- "lastXDirection",
417
- "nowScrolling"
456
+ //#endregion
457
+ //#region src/scroller.ts
458
+ /**
459
+ * Scrollerの状態を示します。
460
+ */
461
+ let ScrollerState = /* @__PURE__ */ function(ScrollerState) {
462
+ /**
463
+ * Scrollerが初期化されていない(Elementが設定されていない)状態を示します。
464
+ */
465
+ ScrollerState["Pending"] = "pending";
466
+ /**
467
+ * Scrollerが初期化されているが、[[Scroller.el]]のリサイズやスクロールのイベント監視が動作していない状態を示します。
468
+ */
469
+ ScrollerState["Ready"] = "ready";
470
+ /**
471
+ * Scrollerが初期化されていて、[[Scroller.el]]のリサイズやスクロールのイベント監視が動作している状態を示します。
472
+ */
473
+ ScrollerState["Running"] = "running";
474
+ /**
475
+ * [[Scroller.destroy]]が実行され、Scrollerが利用不可である状態を示します。
476
+ */
477
+ ScrollerState["Destroyed"] = "destroyed";
478
+ return ScrollerState;
479
+ }({});
480
+ const scrollerObservableKeys = [
481
+ "state",
482
+ "isPending",
483
+ "isReady",
484
+ "isRunning",
485
+ "isDestroyed",
486
+ "scrollEnabled",
487
+ "containerWidth",
488
+ "containerHeight",
489
+ "scrollWidth",
490
+ "scrollHeight",
491
+ "scrollableX",
492
+ "scrollableY",
493
+ "scrollTop",
494
+ "scrollLeft",
495
+ "scrollRight",
496
+ "scrollBottom",
497
+ "lastAxis",
498
+ "lastDirection",
499
+ "lastYDirection",
500
+ "lastXDirection",
501
+ "nowScrolling"
418
502
  ];
503
+ /**
504
+ * 任意のElement(or HTML Document)のスクロールやサイズ変更を監視し、その情報を通知するクラスです。<br>
505
+ * <a href="https://dadajam4.github.io/dadajam4/ev/classes/_ev_.ev.html" target="_blank">EV</a>を継承しており、イベントの購読[[Scroller.on]]等のインターフェースを利用するか、
506
+ * [[Scroller.observe]]メソッドを利用します。<br>
507
+ * [[Scroller.on]]、[[Scroller.once]]で購読可能なイベントについては[[ScrollerEventMap]]を参照してください。
508
+ */
419
509
  var Scroller = class extends EV {
420
- /**
421
- * Scrollerクラスの状態を監視&同期するオブジェクトが
422
- * 保有すべきプロパティ一のキーの配列です。
423
- */
424
- static scrollerObservableKeys = scrollerObservableKeys;
425
- /**
426
- * Scrollerの状態を示すenum値です。
427
- * {@link ScrollerState}
428
- */
429
- static States = ScrollerState;
430
- /**
431
- * スクロールを検知してから、移動がなくなった際に、何ms後にスクロール終了と判定するかのインターバル値を示します。
432
- * デフォルトは500です。
433
- */
434
- scrollingJudgeInterval = 500;
435
- /**
436
- * 縦、横のどちらのスクロールを基準とするかを示します。
437
- * デフォルトはyです。<br>
438
- * この設定は[[Scroller.toElement]]のデフォルト値にも影響します。
439
- */
440
- baseAxis = "y";
441
- /**
442
- * スクロール系メソッド[[Scroller.to]]等を利用する際のデフォルトの設定を示します。
443
- */
444
- scrollSettingsDefaults = { ...defaultBaseSettings };
445
- /**
446
- * [[Scroller.toElement]]のデフォルトオプションの設定を示します。
447
- */
448
- scrollToElementSettingsDefaults = {
449
- ...scrollToElementSettingsDefaults
450
- };
451
- scrollSizeObserver;
452
- /**
453
- * 設定されたElement要素です。
454
- * 初期化が完了していない時には本getterはundefinedを返却する事に注意してください。
455
- */
456
- get el() {
457
- return this._el;
458
- }
459
- /**
460
- * 現在の状態です。<br>
461
- * {@link ScrollerState}
462
- */
463
- get state() {
464
- return this._state;
465
- }
466
- /**
467
- * 未初期化である場合trueを示します。
468
- */
469
- get isPending() {
470
- return this._state === "pending" /* Pending */;
471
- }
472
- /**
473
- * 初期化済み&停止状態である場合trueを示します。
474
- */
475
- get isReady() {
476
- return this._state === "ready" /* Ready */;
477
- }
478
- /**
479
- * 初期化済み&動作中である場合trueを示します。
480
- */
481
- get isRunning() {
482
- return this._state === "running" /* Running */;
483
- }
484
- /**
485
- * インスタンスが破棄済みである場合trueを示します。
486
- */
487
- get isDestroyed() {
488
- return this._state === "destroyed" /* Destroyed */;
489
- }
490
- /**
491
- * スクロールの有効状態を取得します
492
- */
493
- get scrollEnabled() {
494
- return this._scrollStoppers.length === 0;
495
- }
496
- /**
497
- * スクロール要素の幅を示します。
498
- */
499
- get containerWidth() {
500
- return this._containerWidth;
501
- }
502
- /**
503
- * スクロール要素の高さを示します。
504
- */
505
- get containerHeight() {
506
- return this._containerHeight;
507
- }
508
- /**
509
- * スクロール要素内のコンテンツの幅を示します。
510
- */
511
- get scrollWidth() {
512
- return this._scrollWidth;
513
- }
514
- /**
515
- * スクロール要素内のコンテンツの高さを示します。
516
- */
517
- get scrollHeight() {
518
- return this._scrollHeight;
519
- }
520
- /**
521
- * x軸にスクロール可能な場合trueを示します
522
- */
523
- get scrollableX() {
524
- return this._scrollWidth > this._containerWidth;
525
- }
526
- /**
527
- * y軸にスクロール可能な場合trueを示します
528
- */
529
- get scrollableY() {
530
- return this._scrollHeight > this._containerHeight;
531
- }
532
- /**
533
- * 現在の上辺からのスクロール量を示します。
534
- */
535
- get scrollTop() {
536
- return this._scrollTop;
537
- }
538
- set scrollTop(scrollTop) {
539
- if (!this.el) return;
540
- this.el.scrollTop = scrollTop;
541
- }
542
- /**
543
- * 現在の右辺からのスクロール量を示します。
544
- */
545
- get scrollRight() {
546
- return this._scrollRight;
547
- }
548
- set scrollRight(scrollRight) {
549
- if (!this.el) return;
550
- this.el.scrollLeft = this._scrollWidth - this._containerWidth - scrollRight;
551
- }
552
- /**
553
- * 現在の下辺からのスクロール量を示します。
554
- */
555
- get scrollBottom() {
556
- return this._scrollBottom;
557
- }
558
- set scrollBottom(scrollBottom) {
559
- if (!this.el) return;
560
- this.el.scrollTop = this._scrollHeight - this._containerHeight - scrollBottom;
561
- }
562
- /**
563
- * 現在の左辺からのスクロール量を示します。
564
- */
565
- get scrollLeft() {
566
- return this._scrollLeft;
567
- }
568
- set scrollLeft(scrollLeft) {
569
- if (!this.el) return;
570
- this.el.scrollLeft = scrollLeft;
571
- }
572
- /**
573
- * 現在スクロール中である場合trueを示します。
574
- */
575
- get nowScrolling() {
576
- return this._nowScrolling;
577
- }
578
- /**
579
- * 最後に検知したスクロールの軸を示します。
580
- */
581
- get lastAxis() {
582
- return this._lastAxis;
583
- }
584
- /**
585
- * 最後に検知したスクロールの方向を示します。
586
- */
587
- get lastDirection() {
588
- return this._lastDirection;
589
- }
590
- /**
591
- * 最後に検知したスクロールの垂直方向を示します。
592
- */
593
- get lastYDirection() {
594
- return this._lastYDirection;
595
- }
596
- /**
597
- * 最後に検知したスクロールの水平方向を示します。
598
- */
599
- get lastXDirection() {
600
- return this._lastXDirection;
601
- }
602
- /**
603
- * 最後に検知したスクロールにより通知した情報を示します。
604
- */
605
- get lastPayload() {
606
- return {
607
- top: this._scrollTop,
608
- left: this._scrollLeft,
609
- bottom: this._scrollBottom,
610
- right: this._scrollRight,
611
- axis: this._lastAxis,
612
- direction: this._lastDirection,
613
- directionX: this._lastXDirection,
614
- directionY: this._lastYDirection,
615
- tickedX: this._tickedX,
616
- tickedY: this._tickedY,
617
- totalX: this._lastTotalX,
618
- totalY: this._lastTotalY
619
- };
620
- }
621
- _el;
622
- _eventTarget;
623
- _isDocumentElement = false;
624
- _isBodyElement = false;
625
- _isRootElement = false;
626
- _state = "pending" /* Pending */;
627
- _containerWidth = 0;
628
- _containerHeight = 0;
629
- _scrollWidth = 0;
630
- _scrollHeight = 0;
631
- _scrollTop = 0;
632
- _scrollRight = 0;
633
- _scrollBottom = 0;
634
- _scrollLeft = 0;
635
- _lastAxis;
636
- _lastDirection;
637
- _lastYDirection = "top";
638
- _lastXDirection = "left";
639
- _nowScrolling = false;
640
- // eslint-disable-next-line @typescript-eslint/ban-types
641
- _readyResolvers = [];
642
- _scrollingJudgeTimerId = null;
643
- _startX = 0;
644
- _startY = 0;
645
- _tickedX = 0;
646
- _tickedY = 0;
647
- _lastTotalX = 0;
648
- _lastTotalY = 0;
649
- _scrollListener;
650
- _resizeListener;
651
- _resizeObserver;
652
- _scrollToResult = null;
653
- _observers = [];
654
- _scrollStoppers = [];
655
- _scrollSizeObserverPollingId = null;
656
- _scrollSizeObserverSuspended = false;
657
- _visibilityListener;
658
- /**
659
- * Scrollerインスタンスを作成します。
660
- * コンテキストとなるElementをこの時点で指定するか否かは任意です。
661
- *
662
- * @param settingOrElementOrQueryString - 任意です。{@link ScrollerSetting}か Element(or cssクエリセレクタ文字列)を直接指定します。この時点でElementを指定しない場合は、[[setElement]]を実行するまでインスタンスは動作しません。
663
- */
664
- constructor(settingOrElementOrQueryString = {}) {
665
- super();
666
- const convertedSetting = typeof settingOrElementOrQueryString === "string" || settingOrElementOrQueryString === null || IN_WINDOW && settingOrElementOrQueryString instanceof Element ? settingOrElementOrQueryString = {
667
- el: settingOrElementOrQueryString
668
- } : settingOrElementOrQueryString;
669
- if (convertedSetting.scrollingJudgeInterval !== void 0)
670
- this.scrollingJudgeInterval = convertedSetting.scrollingJudgeInterval;
671
- if (convertedSetting.baseAxis) this.baseAxis = convertedSetting.baseAxis;
672
- this._lastAxis = this.baseAxis;
673
- const { scrollSizeObserver } = convertedSetting;
674
- if (scrollSizeObserver) {
675
- this.scrollSizeObserver = {
676
- interval: 500,
677
- width: true,
678
- height: true,
679
- ...scrollSizeObserver
680
- };
681
- }
682
- this._visibilityListener = () => {
683
- if (visibilityManager.isVisible) {
684
- this.update();
685
- if (this._scrollSizeObserverSuspended) {
686
- this._scrollSizeObserverSuspended = false;
687
- this._startScrollSizeObserver();
688
- }
689
- } else {
690
- this._scrollSizeObserverSuspended = this._scrollSizeObserverPollingId !== null;
691
- this._stopScrollSizeObserver();
692
- }
693
- };
694
- this._lastDirection = this._lastAxis === "y" ? "top" : "left";
695
- if (!IN_WINDOW) return;
696
- visibilityManager.change(this._visibilityListener);
697
- this.setElement(convertedSetting.el);
698
- }
699
- /**
700
- * インスタンスにElementを設定します。特別な理由(SSRの利用等)によりコンストラクタでElementを指定できない場合、
701
- * 本メソッドを利用しブラウザコンテキスト配下で本メソッドを実行してください。
702
- * @param el - Element、もしくはCSSクエリセレクタ文字列を指定します。
703
- */
704
- setElement(el) {
705
- if (el === null) return;
706
- if (!IN_WINDOW)
707
- logger.error("Element can be set only when it is under DOM context.");
708
- this.stop();
709
- let _el;
710
- if (typeof el === "string") {
711
- _el = document.querySelector(el);
712
- } else {
713
- _el = el || document.scrollingElement;
714
- }
715
- if (!_el) {
716
- const message = "missing scrolling element";
717
- logger.error(message, el);
718
- throw new Error(message);
719
- }
720
- this._el = _el;
721
- this._isDocumentElement = isDocumentElement(_el);
722
- this._isBodyElement = isBodyElement(_el);
723
- this._isRootElement = this._isDocumentElement || this._isBodyElement;
724
- this._eventTarget = this._isDocumentElement || this._isBodyElement ? window : this._el;
725
- this._setup();
726
- }
727
- _scrollToElementAdditionalOffset;
728
- setScrollToElementAdditionalOffset(offset) {
729
- this._scrollToElementAdditionalOffset = offset;
730
- }
731
- deleteScrollToElementAdditionalOffset() {
732
- delete this._scrollToElementAdditionalOffset;
733
- }
734
- /**
735
- * インスタンスが実行可能になった際にresolveされるPromiseインスタンスを返却します。
736
- */
737
- ready() {
738
- this._checkDestroyed();
739
- if (!this.isPending) return Promise.resolve();
740
- return new Promise((resolve) => this._readyResolvers.push(resolve));
741
- }
742
- /**
743
- * インスタンスの動作を開始します。本インスタンスはElementが設定され初期化された際に自動で動作を開始しますが、
744
- * [[Scroller.stop]]メソッドを利用し動作を停止した後に再開する場合に本メソッドを利用します。
745
- */
746
- async start() {
747
- this._checkDestroyed();
748
- if (this.isRunning) return;
749
- await this.ready();
750
- this._startListeners();
751
- this._setState("running" /* Running */);
752
- }
753
- /**
754
- * インスタンスの動作(スクロール、リサイズイベントの検知等)を停止します。
755
- * 何らかの理由で動作を停止させたい場合に利用してください。
756
- * 本メソッドを実行後もインスタンス内の状態は保持されたままです。
757
- * 完全にインスタンスを破棄するためには[[Scroller.destroy]]を利用してください。
758
- */
759
- stop() {
760
- this._checkDestroyed();
761
- if (!this.isRunning) return;
762
- this._stopListeners();
763
- this._setState("ready" /* Ready */);
764
- }
765
- /**
766
- * インスタンスの動作を停止し、内部情報を完全に破棄します。
767
- * これに伴い、スクロール中であった場合にはキャンセルされ、以後イベント通知は完全に行われません。
768
- * また[[Scroller.start]]メソッドでの再利用も不可となります。
769
- * 本インスタンスの利用を完全に停止する場合に必ず実行し、利用側のオブジェクト等において本インスタンスへの参照を完全に削除してください。
770
- * 本メソッドはSPA等でのサービスにおいては意識的に実行する事を強く推奨します。
771
- */
772
- destroy() {
773
- if (this.isDestroyed) return;
774
- this.stop();
775
- this.cancel();
776
- this._readyResolvers = [];
777
- this._scrollStoppers = [];
778
- this._scrollEnable();
779
- this._observers = [];
780
- visibilityManager.remove(this._visibilityListener);
781
- delete this._el;
782
- delete this._eventTarget;
783
- delete this._scrollListener;
784
- delete this._resizeListener;
785
- delete this._resizeObserver;
786
- delete this._scrollToResult;
787
- delete this._visibilityListener;
788
- this.deleteScrollToElementAdditionalOffset();
789
- this._setState("destroyed" /* Destroyed */);
790
- this.offAll();
791
- }
792
- /**
793
- * インスタンス内部のスクロール量や、Elementのサイズを強制的に更新します。
794
- * 基本的に利用が必要なケースはありませんが、何らかの理由で更新をトリガーしたい場合に利用します。
795
- */
796
- update() {
797
- this._update();
798
- }
799
- /**
800
- * インスタンス内の情報をjsonオブジェクトとして返却します。
801
- * 情報の詳細は[[ScrollerObserver]]を参照してください。
802
- */
803
- toJSON() {
804
- const json = {};
805
- for (const key of scrollerObservableKeys) {
806
- json[key] = this[key];
807
- }
808
- return json;
809
- }
810
- /**
811
- * [[Scroller.toJSON]]の情報を文字列として返却します。
812
- */
813
- toString() {
814
- return JSON.stringify(this.toJSON());
815
- }
816
- /**
817
- * 本インスタンスの情報を購読するためのオブジェクトを設定する事で、
818
- * インスタンスの内部情報が変更される度にパラメータが同期されます。
819
- * 設定するオブジェクトは[[ScrollerObserver]]のインターフェースを満たしていれば内容は問いません。
820
- * 本機能により同期される方法は単純にオブジェクトプロパティへの変数代入です。
821
- * 従って対象となるプロパティをgetterとして実装(Ex: Vue computed等、、)しておく事により、
822
- * 同期を受け取るオブジェクト側でパラメータ変更後の動作をリアクティブに実装可能です。
823
- * @param observer - 同期させたいオブジェクト
824
- * @returns 同期を停止するためのメソッド
825
- */
826
- observe(observer) {
827
- if (!this._observers.includes(observer)) {
828
- this._observers.push(observer);
829
- }
830
- this._syncToObserver(observer);
831
- const unobserve = () => {
832
- this.unobserve(observer);
833
- };
834
- return unobserve;
835
- }
836
- /**
837
- * [[Scroller.observe]]でパラメータ同期中のオブジェクトを停止します。
838
- * [[Scroller.destroy]]実行時にも、同期中のオブジェクトは全停止されますが、destroy前に任意のタイミングで停止したい場合
839
- * 本メソッドを利用します。
840
- * @param observer - 同期中のオブジェクト
841
- */
842
- unobserve(observer) {
843
- const index = this._observers.indexOf(observer);
844
- if (index !== -1) {
845
- this._observers.splice(index, 1);
846
- }
847
- }
848
- /**
849
- * スクロール中であった場合、スクロールをキャンセルします。
850
- */
851
- cancel() {
852
- if (!this._scrollToResult) return;
853
- this._scrollToResult.cancel();
854
- this._clearScrollToResult();
855
- }
856
- /**
857
- * x, yの差分pxを指定しスクロールします。
858
- * メソッド、パラメータの詳細は[[scrollBy]]を参照してください。
859
- * @param diffX - 横移動量
860
- * @param diffY - 縦移動量
861
- * @param options - スクロールオプション
862
- */
863
- by(diffX, diffY, options) {
864
- return this._setScrollToResult(
865
- scrollBy(diffX, diffY, this._createMergedScrollOptions(options))
866
- );
867
- }
868
- /**
869
- * 指定の座標へスクロールします。
870
- * メソッド、パラメータの詳細は[[scrollTo]]を参照してください。
871
- * @param scrollPosition - 座標
872
- * @param options - スクロールオプション
873
- */
874
- to(scrollPosition, options) {
875
- return this._setScrollToResult(
876
- scrollTo(scrollPosition, this._createMergedScrollOptions(options))
877
- );
878
- }
879
- /**
880
- * 指定の要素の位置へスクロールします。
881
- * メソッド、パラメータの詳細は[[scrollToElement]]を参照してください。
882
- * オプションのx, yが未設定であった場合、[[Scroller.baseAxis]]により自動設定されます。
883
- * @param target - スクロール先の要素
884
- * @param options - スクロールオプション
885
- */
886
- toElement(target, options) {
887
- const merged = this._createMergedScrollToElementOptions(options);
888
- if (merged.x === void 0) merged.x = this.baseAxis === "x";
889
- if (merged.y === void 0) merged.y = this.baseAxis === "y";
890
- return this._setScrollToResult(scrollToElement(target, merged));
891
- }
892
- /**
893
- * 指定の辺へスクロールします。
894
- * メソッド、パラメータの詳細は[[scrollToSide]]を参照してください。
895
- * @param targets - スクロール先
896
- * @param options - スクロールオプション
897
- */
898
- toSide(targets, options) {
899
- return this._setScrollToResult(
900
- scrollToSide(targets, this._createMergedScrollOptions(options))
901
- );
902
- }
903
- /**
904
- * 上辺へスクロールします。
905
- * メソッド、パラメータの詳細は[[scrollToTop]]を参照してください。
906
- * @param options - スクロールオプション
907
- */
908
- toTop(options) {
909
- return this._setScrollToResult(
910
- scrollToTop(this._createMergedScrollOptions(options))
911
- );
912
- }
913
- /**
914
- * 右辺へスクロールします。
915
- * メソッド、パラメータの詳細は[[scrollToRight]]を参照してください。
916
- * @param options - スクロールオプション
917
- */
918
- toRight(options) {
919
- return this._setScrollToResult(
920
- scrollToRight(this._createMergedScrollOptions(options))
921
- );
922
- }
923
- /**
924
- * 下辺へスクロールします。
925
- * メソッド、パラメータの詳細は[[scrollToBottom]]を参照してください。
926
- * @param options - スクロールオプション
927
- */
928
- toBottom(options) {
929
- return this._setScrollToResult(
930
- scrollToBottom(this._createMergedScrollOptions(options))
931
- );
932
- }
933
- /**
934
- * 左辺へスクロールします。
935
- * メソッド、パラメータの詳細は[[scrollToLeft]]を参照してください。
936
- * @param options - スクロールオプション
937
- */
938
- toLeft(options) {
939
- return this._setScrollToResult(
940
- scrollToLeft(this._createMergedScrollOptions(options))
941
- );
942
- }
943
- /**
944
- * 左上コーナーへスクロールします。
945
- * メソッド、パラメータの詳細は[[scrollToLeftTop]]を参照してください。
946
- * @param options - スクロールオプション
947
- */
948
- toLeftTop(options) {
949
- return this._setScrollToResult(
950
- scrollToLeftTop(this._createMergedScrollOptions(options))
951
- );
952
- }
953
- /**
954
- * 左下コーナーへスクロールします。
955
- * メソッド、パラメータの詳細は[[scrollToLeftBottom]]を参照してください。
956
- * @param options - スクロールオプション
957
- */
958
- toLeftBottom(options) {
959
- return this._setScrollToResult(
960
- scrollToLeftBottom(this._createMergedScrollOptions(options))
961
- );
962
- }
963
- /**
964
- * 右上コーナーへスクロールします。
965
- * メソッド、パラメータの詳細は[[scrollToRightTop]]を参照してください。
966
- * @param options - スクロールオプション
967
- */
968
- toRightTop(options) {
969
- return this._setScrollToResult(
970
- scrollToRightTop(this._createMergedScrollOptions(options))
971
- );
972
- }
973
- /**
974
- * 右下コーナーへスクロールします。
975
- * メソッド、パラメータの詳細は[[scrollToRightBottom]]を参照してください。
976
- * @param options - スクロールオプション
977
- */
978
- toRightBottom(options) {
979
- return this._setScrollToResult(
980
- scrollToRightBottom(this._createMergedScrollOptions(options))
981
- );
982
- }
983
- /**
984
- * スクロールの停止を要求します。
985
- * @param stopper - 停止要求ソース
986
- */
987
- pushScrollStopper(stopper) {
988
- if (!this._scrollStoppers.includes(stopper)) {
989
- this._scrollStoppers.push(stopper);
990
- if (this._scrollStoppers.length === 1) {
991
- this._updateScrollable();
992
- this._syncToObservers(["scrollEnabled"]);
993
- }
994
- }
995
- return () => {
996
- this.removeScrollStopper(stopper);
997
- };
998
- }
999
- /**
1000
- * スクロールの停止要求を解除します。<br>
1001
- * 別のプロセスにより異なる[[ScrollStopper]]が登録されている場合、
1002
- * スクロールは再開されない事に注意してください。
1003
- * @param stopper - 停止要求ソース
1004
- */
1005
- removeScrollStopper(stopper) {
1006
- const index = this._scrollStoppers.indexOf(stopper);
1007
- if (index !== -1) {
1008
- this._scrollStoppers.splice(index, 1);
1009
- if (this._scrollStoppers.length === 0) {
1010
- this._updateScrollable();
1011
- this._syncToObservers(["scrollEnabled"]);
1012
- }
1013
- }
1014
- }
1015
- async _setup() {
1016
- this._updateScrollable();
1017
- this._update();
1018
- this._setState("ready" /* Ready */);
1019
- this.start();
1020
- this.emit("ready", void 0);
1021
- this._readyResolvers.forEach((resolve) => resolve());
1022
- this._readyResolvers = [];
1023
- }
1024
- _setState(state) {
1025
- if (this._state !== state) {
1026
- this._state = state;
1027
- this._syncToObservers([
1028
- "state",
1029
- "isPending",
1030
- "isReady",
1031
- "isRunning",
1032
- "isDestroyed"
1033
- ]);
1034
- this.emit("changeState", state);
1035
- }
1036
- }
1037
- _checkDestroyed() {
1038
- if (this.isDestroyed) {
1039
- const message = "already destroyed.";
1040
- logger.error(message);
1041
- throw new Error(message);
1042
- }
1043
- }
1044
- _update(width, height) {
1045
- this._updateContainerSize(width, height);
1046
- this._updateScrollSize();
1047
- this._updateScrollPositions();
1048
- }
1049
- _updateContainerSize(width, height) {
1050
- const { el, _isBodyElement } = this;
1051
- if (width === void 0) {
1052
- if (!el) return;
1053
- width = _isBodyElement ? document.documentElement.clientWidth : el.clientWidth;
1054
- }
1055
- if (height === void 0) {
1056
- if (!el) return;
1057
- height = _isBodyElement ? document.documentElement.clientHeight : el.clientHeight;
1058
- }
1059
- const { _containerWidth, _containerHeight } = this;
1060
- this._containerWidth = width;
1061
- this._containerHeight = height;
1062
- if (width !== _containerWidth || height !== _containerHeight) {
1063
- this._syncToObservers([
1064
- "containerWidth",
1065
- "containerHeight",
1066
- "scrollableX",
1067
- "scrollableY"
1068
- ]);
1069
- this.emit("resize", { width, height });
1070
- }
1071
- }
1072
- _updateScrollSize() {
1073
- const { el, _scrollWidth, _scrollHeight } = this;
1074
- if (!el) return;
1075
- this._scrollWidth = el.scrollWidth;
1076
- this._scrollHeight = el.scrollHeight;
1077
- if (_scrollWidth !== this._scrollWidth || _scrollHeight !== this._scrollHeight) {
1078
- this._syncToObservers([
1079
- "scrollWidth",
1080
- "scrollHeight",
1081
- "scrollableX",
1082
- "scrollableY"
1083
- ]);
1084
- }
1085
- }
1086
- _startScrollSizeObserver() {
1087
- if (!IN_WINDOW) return;
1088
- this._stopScrollSizeObserver();
1089
- if (this.scrollSizeObserver) {
1090
- this._scrollSizeObserverPollingId = window.setInterval(() => {
1091
- if (!this.scrollSizeObserver || this.isDestroyed) {
1092
- this._stopScrollSizeObserver();
1093
- return;
1094
- }
1095
- this._updateScrollSize();
1096
- }, this.scrollSizeObserver.interval);
1097
- }
1098
- }
1099
- _stopScrollSizeObserver() {
1100
- if (this._scrollSizeObserverPollingId !== null) {
1101
- clearInterval(this._scrollSizeObserverPollingId);
1102
- this._scrollSizeObserverPollingId = null;
1103
- }
1104
- }
1105
- _updateScrollPositions() {
1106
- if (!this.el) return;
1107
- this._scrollTop = this.el.scrollTop;
1108
- this._scrollLeft = this.el.scrollLeft;
1109
- this._scrollBottom = this._scrollHeight - this._scrollTop - this._containerHeight;
1110
- this._scrollRight = this._scrollWidth - this._scrollLeft - this._containerWidth;
1111
- this._syncToObservers([
1112
- "scrollTop",
1113
- "scrollRight",
1114
- "scrollBottom",
1115
- "scrollLeft"
1116
- ]);
1117
- }
1118
- _startListeners() {
1119
- this._stopListeners();
1120
- this._scrollListener = () => {
1121
- this._onScroll();
1122
- };
1123
- this._eventTarget.addEventListener("scroll", this._scrollListener, false);
1124
- if (this._isRootElement) {
1125
- this._resizeListener = () => {
1126
- this._onResize();
1127
- };
1128
- window.addEventListener("resize", this._resizeListener, false);
1129
- } else {
1130
- this._resizeObserver = new ResizeObserver((entries) => {
1131
- for (const entry of entries) {
1132
- const { width, height } = entry.contentRect;
1133
- this._onResize(width, height);
1134
- }
1135
- });
1136
- this._el && this._resizeObserver.observe(this._el);
1137
- }
1138
- if (visibilityManager.isVisible) {
1139
- this._scrollSizeObserverSuspended = false;
1140
- this._startScrollSizeObserver();
1141
- } else {
1142
- this._scrollSizeObserverSuspended = true;
1143
- }
1144
- }
1145
- _stopListeners() {
1146
- if (this._scrollListener) {
1147
- this._eventTarget.removeEventListener(
1148
- "scroll",
1149
- this._scrollListener,
1150
- false
1151
- );
1152
- delete this._scrollListener;
1153
- }
1154
- if (this._resizeListener) {
1155
- if (this._isDocumentElement) {
1156
- window.removeEventListener("resize", this._resizeListener, false);
1157
- delete this._resizeListener;
1158
- }
1159
- }
1160
- if (this._resizeObserver && this._el) {
1161
- this._resizeObserver.unobserve(this._el);
1162
- this._resizeObserver.disconnect();
1163
- delete this._resizeObserver;
1164
- }
1165
- }
1166
- _clearScrollingJudgeTimer() {
1167
- if (this._scrollingJudgeTimerId !== null) {
1168
- clearTimeout(this._scrollingJudgeTimerId);
1169
- this._scrollingJudgeTimerId = null;
1170
- }
1171
- }
1172
- _onResize(width, height) {
1173
- this._update(width, height);
1174
- }
1175
- _triggerScrollTick(event) {
1176
- const { _nowScrolling } = this;
1177
- if (event === "scrollStart") {
1178
- this._startX = this._scrollLeft;
1179
- this._startY = this._scrollTop;
1180
- this._lastTotalX = 0;
1181
- this._lastTotalY = 0;
1182
- this._nowScrolling = true;
1183
- } else if (event === "scrollEnd") {
1184
- this._nowScrolling = false;
1185
- }
1186
- if (_nowScrolling !== this._nowScrolling) {
1187
- this._syncToObservers("nowScrolling");
1188
- }
1189
- this.emit(event, this.lastPayload);
1190
- }
1191
- _onScroll() {
1192
- if (!this.scrollEnabled && this._el) {
1193
- this._el.scrollLeft = this._scrollLeft;
1194
- this._el.scrollTop = this._scrollTop;
1195
- return;
1196
- }
1197
- const {
1198
- _scrollTop,
1199
- _scrollLeft,
1200
- _lastAxis,
1201
- _lastDirection,
1202
- _lastXDirection,
1203
- _lastYDirection
1204
- } = this;
1205
- this._updateScrollPositions();
1206
- const tickedX = this._scrollLeft - _scrollLeft;
1207
- const tickedY = this._scrollTop - _scrollTop;
1208
- this._tickedX = tickedX;
1209
- this._tickedY = tickedY;
1210
- if (tickedX === tickedY) {
1211
- this._lastAxis = this.baseAxis;
1212
- } else {
1213
- this._lastAxis = Math.abs(tickedX) > Math.abs(tickedY) ? "x" : "y";
1214
- }
1215
- if (_scrollTop < this._scrollTop) {
1216
- this._lastYDirection = "bottom";
1217
- } else if (_scrollTop > this._scrollTop) {
1218
- this._lastYDirection = "top";
1219
- }
1220
- if (_scrollLeft < this._scrollLeft) {
1221
- this._lastXDirection = "right";
1222
- } else if (_scrollLeft > this._scrollLeft) {
1223
- this._lastXDirection = "left";
1224
- }
1225
- this._lastDirection = this._lastAxis === "y" ? this._lastYDirection : this._lastXDirection;
1226
- const axisIsChanged = this._lastAxis !== _lastAxis;
1227
- const lastXDirectionIsChanged = this._lastXDirection !== _lastXDirection;
1228
- const lastYDirectionIsChanged = this._lastYDirection !== _lastYDirection;
1229
- const lastDirectionIsChanged = this._lastDirection !== _lastDirection;
1230
- if (axisIsChanged) {
1231
- this.emit("changeAxis", this._lastAxis);
1232
- }
1233
- if (lastXDirectionIsChanged) {
1234
- this.emit("changeLastXDirection", this._lastXDirection);
1235
- }
1236
- if (lastYDirectionIsChanged) {
1237
- this.emit("changeLastYDirection", this._lastYDirection);
1238
- }
1239
- if (lastDirectionIsChanged) {
1240
- this.emit("changeLastDirection", this._lastDirection);
1241
- }
1242
- if (axisIsChanged || lastXDirectionIsChanged || lastYDirectionIsChanged || lastDirectionIsChanged) {
1243
- this._syncToObservers([
1244
- "lastAxis",
1245
- "lastDirection",
1246
- "lastYDirection",
1247
- "lastXDirection"
1248
- ]);
1249
- }
1250
- if (this._nowScrolling) {
1251
- if (axisIsChanged || _lastAxis === "y" && lastYDirectionIsChanged || _lastAxis === "x" && lastXDirectionIsChanged) {
1252
- this._triggerScrollTick("scrollEnd");
1253
- } else {
1254
- this._lastTotalX = this._scrollLeft - this._startX;
1255
- this._lastTotalY = this._scrollTop - this._startY;
1256
- this._triggerScrollTick("scroll");
1257
- }
1258
- }
1259
- if (!this._nowScrolling) {
1260
- this._updateScrollSize();
1261
- this._triggerScrollTick("scrollStart");
1262
- }
1263
- this._clearScrollingJudgeTimer();
1264
- this._scrollingJudgeTimerId = window.setTimeout(() => {
1265
- this._triggerScrollTick("scrollEnd");
1266
- }, this.scrollingJudgeInterval);
1267
- }
1268
- _syncToObserver(observer, keys = scrollerObservableKeys) {
1269
- for (const key of keys) {
1270
- observer[key] = this[key];
1271
- }
1272
- }
1273
- _syncToObservers(keys) {
1274
- if (this._observers.length === 0) return;
1275
- keys = typeof keys === "string" ? [keys] : keys;
1276
- for (const observer of this._observers) {
1277
- this._syncToObserver(observer, keys);
1278
- }
1279
- }
1280
- _checkElement() {
1281
- const { _el } = this;
1282
- if (!_el) {
1283
- const message = "missing element";
1284
- logger.error(message);
1285
- throw new Error(message);
1286
- }
1287
- return _el;
1288
- }
1289
- _createMergedScrollOptions(source) {
1290
- const el = this._checkElement();
1291
- const merged = {
1292
- container: el,
1293
- ...this.scrollSettingsDefaults,
1294
- ...source
1295
- };
1296
- return merged;
1297
- }
1298
- _createMergedScrollToElementOptions(source) {
1299
- const el = this._checkElement();
1300
- const merged = {
1301
- container: el,
1302
- ...this.scrollToElementSettingsDefaults,
1303
- ...source
1304
- };
1305
- let { _scrollToElementAdditionalOffset: additionalOffset } = this;
1306
- if (!additionalOffset) return merged;
1307
- if (typeof additionalOffset === "function") {
1308
- additionalOffset = additionalOffset(this);
1309
- }
1310
- if (!additionalOffset) return merged;
1311
- if (typeof additionalOffset === "number") {
1312
- additionalOffset = {
1313
- x: additionalOffset,
1314
- y: additionalOffset
1315
- };
1316
- }
1317
- let { offset } = merged;
1318
- if (!offset) {
1319
- merged.offset = additionalOffset;
1320
- return merged;
1321
- }
1322
- if (typeof offset === "number") {
1323
- offset = {
1324
- x: offset,
1325
- y: offset
1326
- };
1327
- }
1328
- offset.x = (offset.x || 0) + (additionalOffset.x || 0);
1329
- offset.y = (offset.y || 0) + (additionalOffset.y || 0);
1330
- merged.offset = offset;
1331
- return merged;
1332
- }
1333
- _clearScrollToResult() {
1334
- if (!this._scrollToResult) return;
1335
- this._scrollToResult = null;
1336
- }
1337
- _setScrollToResult(result) {
1338
- this._scrollToResult = result;
1339
- result.promise.then(() => {
1340
- this._clearScrollToResult();
1341
- });
1342
- return result;
1343
- }
1344
- _updateScrollable() {
1345
- if (this.scrollEnabled) {
1346
- this._scrollEnable();
1347
- } else {
1348
- this._scrollDisable();
1349
- }
1350
- }
1351
- _scrollEnable() {
1352
- enableScroll(this._checkElement());
1353
- }
1354
- _scrollDisable() {
1355
- const el = this._checkElement();
1356
- this.cancel();
1357
- disableScroll(el);
1358
- }
510
+ /**
511
+ * Scrollerクラスの状態を監視&同期するオブジェクトが
512
+ * 保有すべきプロパティ一のキーの配列です。
513
+ */
514
+ static scrollerObservableKeys = scrollerObservableKeys;
515
+ /**
516
+ * Scrollerの状態を示すenum値です。
517
+ * {@link ScrollerState}
518
+ */
519
+ static States = ScrollerState;
520
+ /**
521
+ * スクロールを検知してから、移動がなくなった際に、何ms後にスクロール終了と判定するかのインターバル値を示します。
522
+ * デフォルトは500です。
523
+ */
524
+ scrollingJudgeInterval = 500;
525
+ /**
526
+ * 縦、横のどちらのスクロールを基準とするかを示します。
527
+ * デフォルトはyです。<br>
528
+ * この設定は[[Scroller.toElement]]のデフォルト値にも影響します。
529
+ */
530
+ baseAxis = "y";
531
+ /**
532
+ * スクロール系メソッド[[Scroller.to]]等を利用する際のデフォルトの設定を示します。
533
+ */
534
+ scrollSettingsDefaults = { ...defaultBaseSettings };
535
+ /**
536
+ * [[Scroller.toElement]]のデフォルトオプションの設定を示します。
537
+ */
538
+ scrollToElementSettingsDefaults = { ...scrollToElementSettingsDefaults };
539
+ scrollSizeObserver;
540
+ /**
541
+ * 設定されたElement要素です。
542
+ * 初期化が完了していない時には本getterはundefinedを返却する事に注意してください。
543
+ */
544
+ get el() {
545
+ return this._el;
546
+ }
547
+ /**
548
+ * 現在の状態です。<br>
549
+ * {@link ScrollerState}
550
+ */
551
+ get state() {
552
+ return this._state;
553
+ }
554
+ /**
555
+ * 未初期化である場合trueを示します。
556
+ */
557
+ get isPending() {
558
+ return this._state === ScrollerState.Pending;
559
+ }
560
+ /**
561
+ * 初期化済み&停止状態である場合trueを示します。
562
+ */
563
+ get isReady() {
564
+ return this._state === ScrollerState.Ready;
565
+ }
566
+ /**
567
+ * 初期化済み&動作中である場合trueを示します。
568
+ */
569
+ get isRunning() {
570
+ return this._state === ScrollerState.Running;
571
+ }
572
+ /**
573
+ * インスタンスが破棄済みである場合trueを示します。
574
+ */
575
+ get isDestroyed() {
576
+ return this._state === ScrollerState.Destroyed;
577
+ }
578
+ /**
579
+ * スクロールの有効状態を取得します
580
+ */
581
+ get scrollEnabled() {
582
+ return this._scrollStoppers.length === 0;
583
+ }
584
+ /**
585
+ * スクロール要素の幅を示します。
586
+ */
587
+ get containerWidth() {
588
+ return this._containerWidth;
589
+ }
590
+ /**
591
+ * スクロール要素の高さを示します。
592
+ */
593
+ get containerHeight() {
594
+ return this._containerHeight;
595
+ }
596
+ /**
597
+ * スクロール要素内のコンテンツの幅を示します。
598
+ */
599
+ get scrollWidth() {
600
+ return this._scrollWidth;
601
+ }
602
+ /**
603
+ * スクロール要素内のコンテンツの高さを示します。
604
+ */
605
+ get scrollHeight() {
606
+ return this._scrollHeight;
607
+ }
608
+ /**
609
+ * x軸にスクロール可能な場合trueを示します
610
+ */
611
+ get scrollableX() {
612
+ return this._scrollWidth > this._containerWidth;
613
+ }
614
+ /**
615
+ * y軸にスクロール可能な場合trueを示します
616
+ */
617
+ get scrollableY() {
618
+ return this._scrollHeight > this._containerHeight;
619
+ }
620
+ /**
621
+ * 現在の上辺からのスクロール量を示します。
622
+ */
623
+ get scrollTop() {
624
+ return this._scrollTop;
625
+ }
626
+ set scrollTop(scrollTop) {
627
+ if (!this.el) return;
628
+ this.el.scrollTop = scrollTop;
629
+ }
630
+ /**
631
+ * 現在の右辺からのスクロール量を示します。
632
+ */
633
+ get scrollRight() {
634
+ return this._scrollRight;
635
+ }
636
+ set scrollRight(scrollRight) {
637
+ if (!this.el) return;
638
+ this.el.scrollLeft = this._scrollWidth - this._containerWidth - scrollRight;
639
+ }
640
+ /**
641
+ * 現在の下辺からのスクロール量を示します。
642
+ */
643
+ get scrollBottom() {
644
+ return this._scrollBottom;
645
+ }
646
+ set scrollBottom(scrollBottom) {
647
+ if (!this.el) return;
648
+ this.el.scrollTop = this._scrollHeight - this._containerHeight - scrollBottom;
649
+ }
650
+ /**
651
+ * 現在の左辺からのスクロール量を示します。
652
+ */
653
+ get scrollLeft() {
654
+ return this._scrollLeft;
655
+ }
656
+ set scrollLeft(scrollLeft) {
657
+ if (!this.el) return;
658
+ this.el.scrollLeft = scrollLeft;
659
+ }
660
+ /**
661
+ * 現在スクロール中である場合trueを示します。
662
+ */
663
+ get nowScrolling() {
664
+ return this._nowScrolling;
665
+ }
666
+ /**
667
+ * 最後に検知したスクロールの軸を示します。
668
+ */
669
+ get lastAxis() {
670
+ return this._lastAxis;
671
+ }
672
+ /**
673
+ * 最後に検知したスクロールの方向を示します。
674
+ */
675
+ get lastDirection() {
676
+ return this._lastDirection;
677
+ }
678
+ /**
679
+ * 最後に検知したスクロールの垂直方向を示します。
680
+ */
681
+ get lastYDirection() {
682
+ return this._lastYDirection;
683
+ }
684
+ /**
685
+ * 最後に検知したスクロールの水平方向を示します。
686
+ */
687
+ get lastXDirection() {
688
+ return this._lastXDirection;
689
+ }
690
+ /**
691
+ * 最後に検知したスクロールにより通知した情報を示します。
692
+ */
693
+ get lastPayload() {
694
+ return {
695
+ top: this._scrollTop,
696
+ left: this._scrollLeft,
697
+ bottom: this._scrollBottom,
698
+ right: this._scrollRight,
699
+ axis: this._lastAxis,
700
+ direction: this._lastDirection,
701
+ directionX: this._lastXDirection,
702
+ directionY: this._lastYDirection,
703
+ tickedX: this._tickedX,
704
+ tickedY: this._tickedY,
705
+ totalX: this._lastTotalX,
706
+ totalY: this._lastTotalY
707
+ };
708
+ }
709
+ _el;
710
+ _eventTarget;
711
+ _isDocumentElement = false;
712
+ _isBodyElement = false;
713
+ _isRootElement = false;
714
+ _state = ScrollerState.Pending;
715
+ _containerWidth = 0;
716
+ _containerHeight = 0;
717
+ _scrollWidth = 0;
718
+ _scrollHeight = 0;
719
+ _scrollTop = 0;
720
+ _scrollRight = 0;
721
+ _scrollBottom = 0;
722
+ _scrollLeft = 0;
723
+ _lastAxis;
724
+ _lastDirection;
725
+ _lastYDirection = "top";
726
+ _lastXDirection = "left";
727
+ _nowScrolling = false;
728
+ _readyResolvers = [];
729
+ _scrollingJudgeTimerId = null;
730
+ _startX = 0;
731
+ _startY = 0;
732
+ _tickedX = 0;
733
+ _tickedY = 0;
734
+ _lastTotalX = 0;
735
+ _lastTotalY = 0;
736
+ _scrollListener;
737
+ _resizeListener;
738
+ _resizeObserver;
739
+ _scrollToResult = null;
740
+ _observers = [];
741
+ _scrollStoppers = [];
742
+ _scrollSizeObserverPollingId = null;
743
+ _scrollSizeObserverSuspended = false;
744
+ _visibilityListener;
745
+ /**
746
+ * Scrollerインスタンスを作成します。
747
+ * コンテキストとなるElementをこの時点で指定するか否かは任意です。
748
+ *
749
+ * @param settingOrElementOrQueryString - 任意です。{@link ScrollerSetting}か Element(or cssクエリセレクタ文字列)を直接指定します。この時点でElementを指定しない場合は、[[setElement]]を実行するまでインスタンスは動作しません。
750
+ */
751
+ constructor(settingOrElementOrQueryString = {}) {
752
+ super();
753
+ const convertedSetting = typeof settingOrElementOrQueryString === "string" || settingOrElementOrQueryString === null || IN_WINDOW && settingOrElementOrQueryString instanceof Element ? settingOrElementOrQueryString = { el: settingOrElementOrQueryString } : settingOrElementOrQueryString;
754
+ if (convertedSetting.scrollingJudgeInterval !== void 0) this.scrollingJudgeInterval = convertedSetting.scrollingJudgeInterval;
755
+ if (convertedSetting.baseAxis) this.baseAxis = convertedSetting.baseAxis;
756
+ this._lastAxis = this.baseAxis;
757
+ const { scrollSizeObserver } = convertedSetting;
758
+ if (scrollSizeObserver) this.scrollSizeObserver = {
759
+ interval: 500,
760
+ width: true,
761
+ height: true,
762
+ ...scrollSizeObserver
763
+ };
764
+ this._visibilityListener = () => {
765
+ if (visibilityManager.isVisible) {
766
+ this.update();
767
+ if (this._scrollSizeObserverSuspended) {
768
+ this._scrollSizeObserverSuspended = false;
769
+ this._startScrollSizeObserver();
770
+ }
771
+ } else {
772
+ this._scrollSizeObserverSuspended = this._scrollSizeObserverPollingId !== null;
773
+ this._stopScrollSizeObserver();
774
+ }
775
+ };
776
+ this._lastDirection = this._lastAxis === "y" ? "top" : "left";
777
+ if (!IN_WINDOW) return;
778
+ visibilityManager.change(this._visibilityListener);
779
+ this.setElement(convertedSetting.el);
780
+ }
781
+ /**
782
+ * インスタンスにElementを設定します。特別な理由(SSRの利用等)によりコンストラクタでElementを指定できない場合、
783
+ * 本メソッドを利用しブラウザコンテキスト配下で本メソッドを実行してください。
784
+ * @param el - Element、もしくはCSSクエリセレクタ文字列を指定します。
785
+ */
786
+ setElement(el) {
787
+ if (el === null) return;
788
+ if (!IN_WINDOW) logger.error("Element can be set only when it is under DOM context.");
789
+ this.stop();
790
+ let _el;
791
+ if (typeof el === "string") _el = document.querySelector(el);
792
+ else _el = el || document.scrollingElement;
793
+ if (!_el) {
794
+ const message = "missing scrolling element";
795
+ logger.error(message, el);
796
+ throw new Error(message);
797
+ }
798
+ this._el = _el;
799
+ this._isDocumentElement = isDocumentElement(_el);
800
+ this._isBodyElement = isBodyElement$1(_el);
801
+ this._isRootElement = this._isDocumentElement || this._isBodyElement;
802
+ this._eventTarget = this._isDocumentElement || this._isBodyElement ? window : this._el;
803
+ this._setup();
804
+ }
805
+ _scrollToElementAdditionalOffset;
806
+ setScrollToElementAdditionalOffset(offset) {
807
+ this._scrollToElementAdditionalOffset = offset;
808
+ }
809
+ deleteScrollToElementAdditionalOffset() {
810
+ delete this._scrollToElementAdditionalOffset;
811
+ }
812
+ /**
813
+ * インスタンスが実行可能になった際にresolveされるPromiseインスタンスを返却します。
814
+ */
815
+ ready() {
816
+ this._checkDestroyed();
817
+ if (!this.isPending) return Promise.resolve();
818
+ return new Promise((resolve) => this._readyResolvers.push(resolve));
819
+ }
820
+ /**
821
+ * インスタンスの動作を開始します。本インスタンスはElementが設定され初期化された際に自動で動作を開始しますが、
822
+ * [[Scroller.stop]]メソッドを利用し動作を停止した後に再開する場合に本メソッドを利用します。
823
+ */
824
+ async start() {
825
+ this._checkDestroyed();
826
+ if (this.isRunning) return;
827
+ await this.ready();
828
+ this._startListeners();
829
+ this._setState(ScrollerState.Running);
830
+ }
831
+ /**
832
+ * インスタンスの動作(スクロール、リサイズイベントの検知等)を停止します。
833
+ * 何らかの理由で動作を停止させたい場合に利用してください。
834
+ * 本メソッドを実行後もインスタンス内の状態は保持されたままです。
835
+ * 完全にインスタンスを破棄するためには[[Scroller.destroy]]を利用してください。
836
+ */
837
+ stop() {
838
+ this._checkDestroyed();
839
+ if (!this.isRunning) return;
840
+ this._stopListeners();
841
+ this._setState(ScrollerState.Ready);
842
+ }
843
+ /**
844
+ * インスタンスの動作を停止し、内部情報を完全に破棄します。
845
+ * これに伴い、スクロール中であった場合にはキャンセルされ、以後イベント通知は完全に行われません。
846
+ * また[[Scroller.start]]メソッドでの再利用も不可となります。
847
+ * 本インスタンスの利用を完全に停止する場合に必ず実行し、利用側のオブジェクト等において本インスタンスへの参照を完全に削除してください。
848
+ * 本メソッドはSPA等でのサービスにおいては意識的に実行する事を強く推奨します。
849
+ */
850
+ destroy() {
851
+ if (this.isDestroyed) return;
852
+ this.stop();
853
+ this.cancel();
854
+ this._readyResolvers = [];
855
+ this._scrollStoppers = [];
856
+ this._scrollEnable();
857
+ this._observers = [];
858
+ visibilityManager.remove(this._visibilityListener);
859
+ delete this._el;
860
+ delete this._eventTarget;
861
+ delete this._scrollListener;
862
+ delete this._resizeListener;
863
+ delete this._resizeObserver;
864
+ delete this._scrollToResult;
865
+ delete this._visibilityListener;
866
+ this.deleteScrollToElementAdditionalOffset();
867
+ this._setState(ScrollerState.Destroyed);
868
+ this.offAll();
869
+ }
870
+ /**
871
+ * インスタンス内部のスクロール量や、Elementのサイズを強制的に更新します。
872
+ * 基本的に利用が必要なケースはありませんが、何らかの理由で更新をトリガーしたい場合に利用します。
873
+ */
874
+ update() {
875
+ this._update();
876
+ }
877
+ /**
878
+ * インスタンス内の情報をjsonオブジェクトとして返却します。
879
+ * 情報の詳細は[[ScrollerObserver]]を参照してください。
880
+ */
881
+ toJSON() {
882
+ const json = {};
883
+ for (const key of scrollerObservableKeys) json[key] = this[key];
884
+ return json;
885
+ }
886
+ /**
887
+ * [[Scroller.toJSON]]の情報を文字列として返却します。
888
+ */
889
+ toString() {
890
+ return JSON.stringify(this.toJSON());
891
+ }
892
+ /**
893
+ * 本インスタンスの情報を購読するためのオブジェクトを設定する事で、
894
+ * インスタンスの内部情報が変更される度にパラメータが同期されます。
895
+ * 設定するオブジェクトは[[ScrollerObserver]]のインターフェースを満たしていれば内容は問いません。
896
+ * 本機能により同期される方法は単純にオブジェクトプロパティへの変数代入です。
897
+ * 従って対象となるプロパティをgetterとして実装(Ex: Vue computed等、、)しておく事により、
898
+ * 同期を受け取るオブジェクト側でパラメータ変更後の動作をリアクティブに実装可能です。
899
+ * @param observer - 同期させたいオブジェクト
900
+ * @returns 同期を停止するためのメソッド
901
+ */
902
+ observe(observer) {
903
+ if (!this._observers.includes(observer)) this._observers.push(observer);
904
+ this._syncToObserver(observer);
905
+ const unobserve = () => {
906
+ this.unobserve(observer);
907
+ };
908
+ return unobserve;
909
+ }
910
+ /**
911
+ * [[Scroller.observe]]でパラメータ同期中のオブジェクトを停止します。
912
+ * [[Scroller.destroy]]実行時にも、同期中のオブジェクトは全停止されますが、destroy前に任意のタイミングで停止したい場合
913
+ * 本メソッドを利用します。
914
+ * @param observer - 同期中のオブジェクト
915
+ */
916
+ unobserve(observer) {
917
+ const index = this._observers.indexOf(observer);
918
+ if (index !== -1) this._observers.splice(index, 1);
919
+ }
920
+ /**
921
+ * スクロール中であった場合、スクロールをキャンセルします。
922
+ */
923
+ cancel() {
924
+ if (!this._scrollToResult) return;
925
+ this._scrollToResult.cancel();
926
+ this._clearScrollToResult();
927
+ }
928
+ /**
929
+ * x, yの差分pxを指定しスクロールします。
930
+ * メソッド、パラメータの詳細は[[scrollBy]]を参照してください。
931
+ * @param diffX - 横移動量
932
+ * @param diffY - 縦移動量
933
+ * @param options - スクロールオプション
934
+ */
935
+ by(diffX, diffY, options) {
936
+ return this._setScrollToResult(scrollBy(diffX, diffY, this._createMergedScrollOptions(options)));
937
+ }
938
+ /**
939
+ * 指定の座標へスクロールします。
940
+ * メソッド、パラメータの詳細は[[scrollTo]]を参照してください。
941
+ * @param scrollPosition - 座標
942
+ * @param options - スクロールオプション
943
+ */
944
+ to(scrollPosition, options) {
945
+ return this._setScrollToResult(scrollTo(scrollPosition, this._createMergedScrollOptions(options)));
946
+ }
947
+ /**
948
+ * 指定の要素の位置へスクロールします。
949
+ * メソッド、パラメータの詳細は[[scrollToElement]]を参照してください。
950
+ * オプションのx, yが未設定であった場合、[[Scroller.baseAxis]]により自動設定されます。
951
+ * @param target - スクロール先の要素
952
+ * @param options - スクロールオプション
953
+ */
954
+ toElement(target, options) {
955
+ const merged = this._createMergedScrollToElementOptions(options);
956
+ if (merged.x === void 0) merged.x = this.baseAxis === "x";
957
+ if (merged.y === void 0) merged.y = this.baseAxis === "y";
958
+ return this._setScrollToResult(scrollToElement(target, merged));
959
+ }
960
+ /**
961
+ * 指定の辺へスクロールします。
962
+ * メソッド、パラメータの詳細は[[scrollToSide]]を参照してください。
963
+ * @param targets - スクロール先
964
+ * @param options - スクロールオプション
965
+ */
966
+ toSide(targets, options) {
967
+ return this._setScrollToResult(scrollToSide(targets, this._createMergedScrollOptions(options)));
968
+ }
969
+ /**
970
+ * 上辺へスクロールします。
971
+ * メソッド、パラメータの詳細は[[scrollToTop]]を参照してください。
972
+ * @param options - スクロールオプション
973
+ */
974
+ toTop(options) {
975
+ return this._setScrollToResult(scrollToTop(this._createMergedScrollOptions(options)));
976
+ }
977
+ /**
978
+ * 右辺へスクロールします。
979
+ * メソッド、パラメータの詳細は[[scrollToRight]]を参照してください。
980
+ * @param options - スクロールオプション
981
+ */
982
+ toRight(options) {
983
+ return this._setScrollToResult(scrollToRight(this._createMergedScrollOptions(options)));
984
+ }
985
+ /**
986
+ * 下辺へスクロールします。
987
+ * メソッド、パラメータの詳細は[[scrollToBottom]]を参照してください。
988
+ * @param options - スクロールオプション
989
+ */
990
+ toBottom(options) {
991
+ return this._setScrollToResult(scrollToBottom(this._createMergedScrollOptions(options)));
992
+ }
993
+ /**
994
+ * 左辺へスクロールします。
995
+ * メソッド、パラメータの詳細は[[scrollToLeft]]を参照してください。
996
+ * @param options - スクロールオプション
997
+ */
998
+ toLeft(options) {
999
+ return this._setScrollToResult(scrollToLeft(this._createMergedScrollOptions(options)));
1000
+ }
1001
+ /**
1002
+ * 左上コーナーへスクロールします。
1003
+ * メソッド、パラメータの詳細は[[scrollToLeftTop]]を参照してください。
1004
+ * @param options - スクロールオプション
1005
+ */
1006
+ toLeftTop(options) {
1007
+ return this._setScrollToResult(scrollToLeftTop(this._createMergedScrollOptions(options)));
1008
+ }
1009
+ /**
1010
+ * 左下コーナーへスクロールします。
1011
+ * メソッド、パラメータの詳細は[[scrollToLeftBottom]]を参照してください。
1012
+ * @param options - スクロールオプション
1013
+ */
1014
+ toLeftBottom(options) {
1015
+ return this._setScrollToResult(scrollToLeftBottom(this._createMergedScrollOptions(options)));
1016
+ }
1017
+ /**
1018
+ * 右上コーナーへスクロールします。
1019
+ * メソッド、パラメータの詳細は[[scrollToRightTop]]を参照してください。
1020
+ * @param options - スクロールオプション
1021
+ */
1022
+ toRightTop(options) {
1023
+ return this._setScrollToResult(scrollToRightTop(this._createMergedScrollOptions(options)));
1024
+ }
1025
+ /**
1026
+ * 右下コーナーへスクロールします。
1027
+ * メソッド、パラメータの詳細は[[scrollToRightBottom]]を参照してください。
1028
+ * @param options - スクロールオプション
1029
+ */
1030
+ toRightBottom(options) {
1031
+ return this._setScrollToResult(scrollToRightBottom(this._createMergedScrollOptions(options)));
1032
+ }
1033
+ /**
1034
+ * スクロールの停止を要求します。
1035
+ * @param stopper - 停止要求ソース
1036
+ */
1037
+ pushScrollStopper(stopper) {
1038
+ if (!this._scrollStoppers.includes(stopper)) {
1039
+ this._scrollStoppers.push(stopper);
1040
+ if (this._scrollStoppers.length === 1) {
1041
+ this._updateScrollable();
1042
+ this._syncToObservers(["scrollEnabled"]);
1043
+ }
1044
+ }
1045
+ return () => {
1046
+ this.removeScrollStopper(stopper);
1047
+ };
1048
+ }
1049
+ /**
1050
+ * スクロールの停止要求を解除します。<br>
1051
+ * 別のプロセスにより異なる[[ScrollStopper]]が登録されている場合、
1052
+ * スクロールは再開されない事に注意してください。
1053
+ * @param stopper - 停止要求ソース
1054
+ */
1055
+ removeScrollStopper(stopper) {
1056
+ const index = this._scrollStoppers.indexOf(stopper);
1057
+ if (index !== -1) {
1058
+ this._scrollStoppers.splice(index, 1);
1059
+ if (this._scrollStoppers.length === 0) {
1060
+ this._updateScrollable();
1061
+ this._syncToObservers(["scrollEnabled"]);
1062
+ }
1063
+ }
1064
+ }
1065
+ async _setup() {
1066
+ this._updateScrollable();
1067
+ this._update();
1068
+ this._setState(ScrollerState.Ready);
1069
+ this.start();
1070
+ this.emit("ready", void 0);
1071
+ this._readyResolvers.forEach((resolve) => resolve());
1072
+ this._readyResolvers = [];
1073
+ }
1074
+ _setState(state) {
1075
+ if (this._state !== state) {
1076
+ this._state = state;
1077
+ this._syncToObservers([
1078
+ "state",
1079
+ "isPending",
1080
+ "isReady",
1081
+ "isRunning",
1082
+ "isDestroyed"
1083
+ ]);
1084
+ this.emit("changeState", state);
1085
+ }
1086
+ }
1087
+ _checkDestroyed() {
1088
+ if (this.isDestroyed) {
1089
+ const message = "already destroyed.";
1090
+ logger.error(message);
1091
+ throw new Error(message);
1092
+ }
1093
+ }
1094
+ _update(width, height) {
1095
+ this._updateContainerSize(width, height);
1096
+ this._updateScrollSize();
1097
+ this._updateScrollPositions();
1098
+ }
1099
+ _updateContainerSize(width, height) {
1100
+ const { el, _isBodyElement } = this;
1101
+ if (width === void 0) {
1102
+ if (!el) return;
1103
+ width = _isBodyElement ? document.documentElement.clientWidth : el.clientWidth;
1104
+ }
1105
+ if (height === void 0) {
1106
+ if (!el) return;
1107
+ height = _isBodyElement ? document.documentElement.clientHeight : el.clientHeight;
1108
+ }
1109
+ const { _containerWidth, _containerHeight } = this;
1110
+ this._containerWidth = width;
1111
+ this._containerHeight = height;
1112
+ if (width !== _containerWidth || height !== _containerHeight) {
1113
+ this._syncToObservers([
1114
+ "containerWidth",
1115
+ "containerHeight",
1116
+ "scrollableX",
1117
+ "scrollableY"
1118
+ ]);
1119
+ this.emit("resize", {
1120
+ width,
1121
+ height
1122
+ });
1123
+ }
1124
+ }
1125
+ _updateScrollSize() {
1126
+ const { el, _scrollWidth, _scrollHeight } = this;
1127
+ if (!el) return;
1128
+ this._scrollWidth = el.scrollWidth;
1129
+ this._scrollHeight = el.scrollHeight;
1130
+ if (_scrollWidth !== this._scrollWidth || _scrollHeight !== this._scrollHeight) this._syncToObservers([
1131
+ "scrollWidth",
1132
+ "scrollHeight",
1133
+ "scrollableX",
1134
+ "scrollableY"
1135
+ ]);
1136
+ }
1137
+ _startScrollSizeObserver() {
1138
+ if (!IN_WINDOW) return;
1139
+ this._stopScrollSizeObserver();
1140
+ if (this.scrollSizeObserver) this._scrollSizeObserverPollingId = window.setInterval(() => {
1141
+ if (!this.scrollSizeObserver || this.isDestroyed) {
1142
+ this._stopScrollSizeObserver();
1143
+ return;
1144
+ }
1145
+ this._updateScrollSize();
1146
+ }, this.scrollSizeObserver.interval);
1147
+ }
1148
+ _stopScrollSizeObserver() {
1149
+ if (this._scrollSizeObserverPollingId !== null) {
1150
+ clearInterval(this._scrollSizeObserverPollingId);
1151
+ this._scrollSizeObserverPollingId = null;
1152
+ }
1153
+ }
1154
+ _updateScrollPositions() {
1155
+ if (!this.el) return;
1156
+ this._scrollTop = this.el.scrollTop;
1157
+ this._scrollLeft = this.el.scrollLeft;
1158
+ this._scrollBottom = this._scrollHeight - this._scrollTop - this._containerHeight;
1159
+ this._scrollRight = this._scrollWidth - this._scrollLeft - this._containerWidth;
1160
+ this._syncToObservers([
1161
+ "scrollTop",
1162
+ "scrollRight",
1163
+ "scrollBottom",
1164
+ "scrollLeft"
1165
+ ]);
1166
+ }
1167
+ _startListeners() {
1168
+ this._stopListeners();
1169
+ this._scrollListener = () => {
1170
+ this._onScroll();
1171
+ };
1172
+ this._eventTarget.addEventListener("scroll", this._scrollListener, false);
1173
+ if (this._isRootElement) {
1174
+ this._resizeListener = () => {
1175
+ this._onResize();
1176
+ };
1177
+ window.addEventListener("resize", this._resizeListener, false);
1178
+ } else {
1179
+ this._resizeObserver = new ResizeObserver((entries) => {
1180
+ for (const entry of entries) {
1181
+ const { width, height } = entry.contentRect;
1182
+ this._onResize(width, height);
1183
+ }
1184
+ });
1185
+ this._el && this._resizeObserver.observe(this._el);
1186
+ }
1187
+ if (visibilityManager.isVisible) {
1188
+ this._scrollSizeObserverSuspended = false;
1189
+ this._startScrollSizeObserver();
1190
+ } else this._scrollSizeObserverSuspended = true;
1191
+ }
1192
+ _stopListeners() {
1193
+ if (this._scrollListener) {
1194
+ this._eventTarget.removeEventListener("scroll", this._scrollListener, false);
1195
+ delete this._scrollListener;
1196
+ }
1197
+ if (this._resizeListener) {
1198
+ if (this._isDocumentElement) {
1199
+ window.removeEventListener("resize", this._resizeListener, false);
1200
+ delete this._resizeListener;
1201
+ }
1202
+ }
1203
+ if (this._resizeObserver && this._el) {
1204
+ this._resizeObserver.unobserve(this._el);
1205
+ this._resizeObserver.disconnect();
1206
+ delete this._resizeObserver;
1207
+ }
1208
+ }
1209
+ _clearScrollingJudgeTimer() {
1210
+ if (this._scrollingJudgeTimerId !== null) {
1211
+ clearTimeout(this._scrollingJudgeTimerId);
1212
+ this._scrollingJudgeTimerId = null;
1213
+ }
1214
+ }
1215
+ _onResize(width, height) {
1216
+ this._update(width, height);
1217
+ }
1218
+ _triggerScrollTick(event) {
1219
+ const { _nowScrolling } = this;
1220
+ if (event === "scrollStart") {
1221
+ this._startX = this._scrollLeft;
1222
+ this._startY = this._scrollTop;
1223
+ this._lastTotalX = 0;
1224
+ this._lastTotalY = 0;
1225
+ this._nowScrolling = true;
1226
+ } else if (event === "scrollEnd") this._nowScrolling = false;
1227
+ if (_nowScrolling !== this._nowScrolling) this._syncToObservers("nowScrolling");
1228
+ this.emit(event, this.lastPayload);
1229
+ }
1230
+ _onScroll() {
1231
+ if (!this.scrollEnabled && this._el) {
1232
+ this._el.scrollLeft = this._scrollLeft;
1233
+ this._el.scrollTop = this._scrollTop;
1234
+ return;
1235
+ }
1236
+ const { _scrollTop, _scrollLeft, _lastAxis, _lastDirection, _lastXDirection, _lastYDirection } = this;
1237
+ this._updateScrollPositions();
1238
+ const tickedX = this._scrollLeft - _scrollLeft;
1239
+ const tickedY = this._scrollTop - _scrollTop;
1240
+ this._tickedX = tickedX;
1241
+ this._tickedY = tickedY;
1242
+ if (tickedX === tickedY) this._lastAxis = this.baseAxis;
1243
+ else this._lastAxis = Math.abs(tickedX) > Math.abs(tickedY) ? "x" : "y";
1244
+ if (_scrollTop < this._scrollTop) this._lastYDirection = "bottom";
1245
+ else if (_scrollTop > this._scrollTop) this._lastYDirection = "top";
1246
+ if (_scrollLeft < this._scrollLeft) this._lastXDirection = "right";
1247
+ else if (_scrollLeft > this._scrollLeft) this._lastXDirection = "left";
1248
+ this._lastDirection = this._lastAxis === "y" ? this._lastYDirection : this._lastXDirection;
1249
+ const axisIsChanged = this._lastAxis !== _lastAxis;
1250
+ const lastXDirectionIsChanged = this._lastXDirection !== _lastXDirection;
1251
+ const lastYDirectionIsChanged = this._lastYDirection !== _lastYDirection;
1252
+ const lastDirectionIsChanged = this._lastDirection !== _lastDirection;
1253
+ if (axisIsChanged) this.emit("changeAxis", this._lastAxis);
1254
+ if (lastXDirectionIsChanged) this.emit("changeLastXDirection", this._lastXDirection);
1255
+ if (lastYDirectionIsChanged) this.emit("changeLastYDirection", this._lastYDirection);
1256
+ if (lastDirectionIsChanged) this.emit("changeLastDirection", this._lastDirection);
1257
+ if (axisIsChanged || lastXDirectionIsChanged || lastYDirectionIsChanged || lastDirectionIsChanged) this._syncToObservers([
1258
+ "lastAxis",
1259
+ "lastDirection",
1260
+ "lastYDirection",
1261
+ "lastXDirection"
1262
+ ]);
1263
+ if (this._nowScrolling) if (axisIsChanged || _lastAxis === "y" && lastYDirectionIsChanged || _lastAxis === "x" && lastXDirectionIsChanged) this._triggerScrollTick("scrollEnd");
1264
+ else {
1265
+ this._lastTotalX = this._scrollLeft - this._startX;
1266
+ this._lastTotalY = this._scrollTop - this._startY;
1267
+ this._triggerScrollTick("scroll");
1268
+ }
1269
+ if (!this._nowScrolling) {
1270
+ this._updateScrollSize();
1271
+ this._triggerScrollTick("scrollStart");
1272
+ }
1273
+ this._clearScrollingJudgeTimer();
1274
+ this._scrollingJudgeTimerId = window.setTimeout(() => {
1275
+ this._triggerScrollTick("scrollEnd");
1276
+ }, this.scrollingJudgeInterval);
1277
+ }
1278
+ _syncToObserver(observer, keys = scrollerObservableKeys) {
1279
+ for (const key of keys) observer[key] = this[key];
1280
+ }
1281
+ _syncToObservers(keys) {
1282
+ if (this._observers.length === 0) return;
1283
+ keys = typeof keys === "string" ? [keys] : keys;
1284
+ for (const observer of this._observers) this._syncToObserver(observer, keys);
1285
+ }
1286
+ _checkElement() {
1287
+ const { _el } = this;
1288
+ if (!_el) {
1289
+ const message = "missing element";
1290
+ logger.error(message);
1291
+ throw new Error(message);
1292
+ }
1293
+ return _el;
1294
+ }
1295
+ _createMergedScrollOptions(source) {
1296
+ return {
1297
+ container: this._checkElement(),
1298
+ ...this.scrollSettingsDefaults,
1299
+ ...source
1300
+ };
1301
+ }
1302
+ _createMergedScrollToElementOptions(source) {
1303
+ const merged = {
1304
+ container: this._checkElement(),
1305
+ ...this.scrollToElementSettingsDefaults,
1306
+ ...source
1307
+ };
1308
+ let { _scrollToElementAdditionalOffset: additionalOffset } = this;
1309
+ if (!additionalOffset) return merged;
1310
+ if (typeof additionalOffset === "function") additionalOffset = additionalOffset(this);
1311
+ if (!additionalOffset) return merged;
1312
+ if (typeof additionalOffset === "number") additionalOffset = {
1313
+ x: additionalOffset,
1314
+ y: additionalOffset
1315
+ };
1316
+ let { offset } = merged;
1317
+ if (!offset) {
1318
+ merged.offset = additionalOffset;
1319
+ return merged;
1320
+ }
1321
+ if (typeof offset === "number") offset = {
1322
+ x: offset,
1323
+ y: offset
1324
+ };
1325
+ offset.x = (offset.x || 0) + (additionalOffset.x || 0);
1326
+ offset.y = (offset.y || 0) + (additionalOffset.y || 0);
1327
+ merged.offset = offset;
1328
+ return merged;
1329
+ }
1330
+ _clearScrollToResult() {
1331
+ if (!this._scrollToResult) return;
1332
+ this._scrollToResult = null;
1333
+ }
1334
+ _setScrollToResult(result) {
1335
+ this._scrollToResult = result;
1336
+ result.promise.then(() => {
1337
+ this._clearScrollToResult();
1338
+ });
1339
+ return result;
1340
+ }
1341
+ _updateScrollable() {
1342
+ if (this.scrollEnabled) this._scrollEnable();
1343
+ else this._scrollDisable();
1344
+ }
1345
+ _scrollEnable() {
1346
+ enableScroll(this._checkElement());
1347
+ }
1348
+ _scrollDisable() {
1349
+ const el = this._checkElement();
1350
+ this.cancel();
1351
+ disableScroll(el);
1352
+ }
1359
1353
  };
1360
1354
 
1355
+ //#endregion
1361
1356
  export { SCROLLABLE_KEY_CODES, Scroller, ScrollerState, defaultBaseSettings, defaultSettings, disableScroll, enableScroll, scrollBy, scrollTo, scrollToBottom, scrollToElement, scrollToElementSettingsDefaults, scrollToLeft, scrollToLeftBottom, scrollToLeftTop, scrollToRight, scrollToRightBottom, scrollToRightTop, scrollToSide, scrollToTop };
1362
- //# sourceMappingURL=scroller.mjs.map
1363
1357
  //# sourceMappingURL=scroller.mjs.map