@leafer-in/scroller 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023-present, Chao (Leafer) Wan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @leafer-in/scroller
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+
3
+ var core = require("@leafer-ui/core");
4
+
5
+ const config = {
6
+ theme: "light",
7
+ style: {
8
+ dragBoundsType: "outer",
9
+ strokeAlign: "center",
10
+ strokeWidthFixed: "zoom-in",
11
+ width: 6,
12
+ height: 6,
13
+ opacity: .5,
14
+ cornerRadius: 3,
15
+ hoverStyle: {
16
+ opacity: .6
17
+ },
18
+ pressStyle: {
19
+ opacity: .66
20
+ }
21
+ },
22
+ size: 6,
23
+ endsMargin: 2,
24
+ sideMargin: 2,
25
+ minSize: 10,
26
+ scaleFixed: "zoom-in",
27
+ scrollType: "both",
28
+ hideOnActionEnd: "hover"
29
+ };
30
+
31
+ const tempBounds = new core.Bounds, {float: float} = core.MathHelper, {clone: clone, assign: assign} = core.DataHelper;
32
+
33
+ class Scroller extends core.Group {
34
+ get canUse() {
35
+ return this.target.hasScroller;
36
+ }
37
+ constructor(target) {
38
+ super();
39
+ this.targetWorldBounds = new core.Bounds;
40
+ this.viewportBounds = new core.Bounds;
41
+ this.contentBounds = new core.Bounds;
42
+ this.scrollXBounds = new core.Bounds;
43
+ this.scrollYBounds = new core.Bounds;
44
+ this.target = target;
45
+ this.config = clone(config);
46
+ this.updateConfig();
47
+ this.__listenEvents();
48
+ target.waitLeafer(() => {
49
+ this.parent = target;
50
+ this.__bindLeafer(target.leafer);
51
+ });
52
+ if (this.mergedConfig.hideOnActionEnd) this.opacity = 0;
53
+ }
54
+ static registerTheme(theme, themeConfig) {
55
+ S.themeMap[theme] = themeConfig;
56
+ }
57
+ static getTheme(theme) {
58
+ return theme && S.themeMap[theme];
59
+ }
60
+ static hasTheme(theme) {
61
+ return theme && !!S.themeMap[theme];
62
+ }
63
+ updateConfig() {
64
+ const {scrollConfig: scrollConfig} = this.target;
65
+ const themeConfig = S.getTheme(scrollConfig && S.hasTheme(scrollConfig.theme) && scrollConfig.theme || this.config.theme);
66
+ const mergedConfig = this.mergedConfig = clone(this.config);
67
+ assign(mergedConfig, themeConfig);
68
+ if (scrollConfig) assign(mergedConfig, scrollConfig);
69
+ this.updateStyle(mergedConfig.style);
70
+ }
71
+ updateStyle(style) {
72
+ if (!this.scrollXBar) this.addMany(this.scrollXBar = new core.Box, this.scrollYBar = new core.Box);
73
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar} = this;
74
+ scrollXBar.set(style);
75
+ scrollYBar.set(style);
76
+ scrollXBar.draggable = "x";
77
+ scrollYBar.draggable = "y";
78
+ }
79
+ update(check = true) {
80
+ if (this.dragScrolling) return;
81
+ const {target: target, targetOverflow: targetOverflow, targetWorldBounds: targetWorldBounds, viewportBounds: viewportBounds, contentBounds: contentBounds} = this, layout = target.__layout, {overflow: overflow} = target.__;
82
+ const {childrenRenderBounds: childrenRenderBounds} = layout;
83
+ const {boxBounds: boxBounds, worldBoxBounds: worldBoxBounds} = layout;
84
+ const isSameWorldBounds = check && targetOverflow === overflow && targetWorldBounds.isSame(worldBoxBounds);
85
+ const isSameConfig = layout.scrollConfigChanged ? (this.updateConfig(), layout.scrollConfigChanged = false) : true;
86
+ const nowContentBounds = tempBounds.set(viewportBounds).add(childrenRenderBounds);
87
+ if (isSameWorldBounds && isSameConfig && contentBounds.isSame(nowContentBounds)) return;
88
+ this.targetOverflow = overflow;
89
+ viewportBounds.set(boxBounds);
90
+ targetWorldBounds.set(worldBoxBounds);
91
+ contentBounds.set(nowContentBounds);
92
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar} = this, {size: size, endsMargin: endsMargin, minSize: minSize} = this.mergedConfig, {width: width, height: height} = viewportBounds;
93
+ this.contentRealX = contentBounds.x - target.scrollX;
94
+ this.contentRealY = contentBounds.y - target.scrollY;
95
+ this.ratioX = viewportBounds.width / contentBounds.width;
96
+ this.ratioY = viewportBounds.height / contentBounds.height;
97
+ const min = size + endsMargin * 2 + minSize;
98
+ scrollXBar.visible = float(contentBounds.width) > float(width) && overflow !== "y-scroll" && width > min;
99
+ scrollYBar.visible = float(contentBounds.height) > float(height) && overflow !== "x-scroll" && height > min;
100
+ this.updateScrollBar();
101
+ }
102
+ updateScrollBar() {
103
+ const {target: target, viewportBounds: viewportBounds, contentBounds: contentBounds, ratioX: ratioX, ratioY: ratioY, scrollXBar: scrollXBar, scrollYBar: scrollYBar, scrollXBounds: scrollXBounds, scrollYBounds: scrollYBounds} = this;
104
+ let {size: size, cornerRadius: cornerRadius, endsMargin: endsMargin, sideMargin: sideMargin, minSize: minSize, scaleFixed: scaleFixed, scrollType: scrollType} = this.mergedConfig;
105
+ const scale = scaleFixed ? target.getClampRenderScale() : 1;
106
+ endsMargin /= scale;
107
+ sideMargin /= scale;
108
+ size /= scale;
109
+ if (core.isUndefined(cornerRadius)) cornerRadius = size / 2;
110
+ if (scrollXBar.visible) {
111
+ scrollXBounds.set(viewportBounds).shrink([ endsMargin, scrollYBar.visible ? size + sideMargin : endsMargin, sideMargin, endsMargin ]);
112
+ const scrollRatioX = this.scrollRatioX = scrollXBounds.width / contentBounds.width;
113
+ scrollXBar.set({
114
+ x: scrollXBounds.x - contentBounds.x * scrollRatioX,
115
+ y: scrollXBounds.maxY - size,
116
+ width: Math.max(scrollXBounds.width * ratioX, minSize),
117
+ height: size,
118
+ cornerRadius: cornerRadius,
119
+ dragBounds: scrollXBounds,
120
+ hittable: scrollType !== "move"
121
+ });
122
+ }
123
+ if (scrollYBar.visible) {
124
+ scrollYBounds.set(viewportBounds).shrink([ endsMargin, sideMargin, scrollXBar.visible ? size + sideMargin : endsMargin, endsMargin ]);
125
+ const scrollRatioY = this.scrollRatioY = scrollYBounds.height / contentBounds.height;
126
+ scrollYBar.set({
127
+ x: scrollYBounds.maxX - size,
128
+ y: scrollYBounds.y - contentBounds.y * scrollRatioY,
129
+ width: size,
130
+ height: Math.max(scrollYBounds.height * ratioY, minSize),
131
+ cornerRadius: cornerRadius,
132
+ dragBounds: scrollYBounds,
133
+ hittable: scrollType !== "move"
134
+ });
135
+ }
136
+ this.x = -this.target.scrollX;
137
+ this.y = -this.target.scrollY;
138
+ core.LeafHelper.updateAllMatrix(this);
139
+ core.BranchHelper.updateBounds(this);
140
+ core.LeafHelper.updateAllChange(this);
141
+ }
142
+ onDrag(e) {
143
+ if (this.mergedConfig.scrollType === "move") return;
144
+ this.dragScrolling = true;
145
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar, target: target, scrollXBounds: scrollXBounds, scrollYBounds: scrollYBounds} = this;
146
+ const scrollX = e.current === scrollXBar;
147
+ if (scrollX) target.scrollX = -((scrollXBar.x - scrollXBounds.x) / this.scrollRatioX + this.contentRealX); else target.scrollY = -((scrollYBar.y - scrollYBounds.y) / this.scrollRatioY + this.contentRealY);
148
+ }
149
+ onDragEnd() {
150
+ if (this.mergedConfig.scrollType === "move") return;
151
+ this.dragScrolling = false;
152
+ }
153
+ onMove(e) {
154
+ if (!this.canUse) return;
155
+ this.onEnter();
156
+ const {scrollType: scrollType, stopDefault: stopDefault} = this.mergedConfig;
157
+ if (scrollType === "drag") return;
158
+ const {viewportBounds: viewportBounds, contentBounds: contentBounds, scrollXBar: scrollXBar, scrollYBar: scrollYBar} = this;
159
+ if (scrollXBar.visible || scrollYBar.visible) {
160
+ const move = e.getInnerMove(this.target);
161
+ core.DragBoundsHelper.getValidMove(contentBounds, viewportBounds, "inner", move, true);
162
+ let needStop;
163
+ if (move.x && scrollXBar.visible) this.target.scrollX += move.x, needStop = true;
164
+ if (move.y && scrollYBar.visible) this.target.scrollY += move.y, needStop = true;
165
+ if (needStop || stopDefault) e.stop();
166
+ if (stopDefault) e.stopDefault();
167
+ }
168
+ }
169
+ onMoveEnd(e) {
170
+ if (!this.canUse) return;
171
+ if (!this.target.hit(e)) this.onLeave();
172
+ }
173
+ onEnter() {
174
+ if (!this.canUse) return;
175
+ clearTimeout(this.hideTimer);
176
+ this.killAnimate();
177
+ this.opacity = 1;
178
+ }
179
+ onLeave() {
180
+ if (!this.canUse) return;
181
+ clearTimeout(this.hideTimer);
182
+ if (this.mergedConfig.hideOnActionEnd) this.hideTimer = setTimeout(() => {
183
+ this.set({
184
+ opacity: 0
185
+ }, core.Plugin.has("animate"));
186
+ }, 600);
187
+ }
188
+ onResize() {
189
+ if (this.canUse) this.update();
190
+ }
191
+ __listenEvents() {
192
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar, target: target} = this;
193
+ this.__eventIds = [ scrollXBar.on_(core.DragEvent.DRAG, this.onDrag, this), scrollXBar.on_(core.DragEvent.END, this.onDragEnd, this), scrollYBar.on_(core.DragEvent.DRAG, this.onDrag, this), scrollYBar.on_(core.DragEvent.END, this.onDragEnd, this), target.on_(core.PointerEvent.ENTER, this.onEnter, this), target.on_(core.PointerEvent.LEAVE, this.onLeave, this), target.on_(core.MoveEvent.BEFORE_MOVE, this.onMove, this), target.on_(core.MoveEvent.END, this.onMoveEnd, this), target.on_(core.BoundsEvent.WORLD, this.onResize, this), target.on_(core.ChildEvent.DESTROY, this.destroy, this) ];
194
+ }
195
+ __removeListenEvents() {
196
+ this.off_(this.__eventIds);
197
+ }
198
+ destroy() {
199
+ if (!this.destroyed) {
200
+ this.__removeListenEvents();
201
+ const {target: target} = this;
202
+ target.scroller = target.topChildren = target.hasScroller = undefined;
203
+ this.target = this.config = null;
204
+ super.destroy();
205
+ }
206
+ }
207
+ }
208
+
209
+ Scroller.themeMap = {};
210
+
211
+ const S = Scroller;
212
+
213
+ function scrollConfigType(defaultValue) {
214
+ return core.decorateLeafAttr(defaultValue, key => core.attr({
215
+ set(value) {
216
+ if (this.__setAttr(key, value)) {
217
+ const layout = this.__layout;
218
+ layout.scrollConfigChanged = true;
219
+ core.doBoundsType(this);
220
+ }
221
+ }
222
+ }));
223
+ }
224
+
225
+ core.Plugin.add("scroller");
226
+
227
+ const box = core.Box.prototype;
228
+
229
+ core.Box.addAttr("scrollConfig", undefined, scrollConfigType);
230
+
231
+ box.__checkScroll = function(isScrollMode) {
232
+ if (isScrollMode && this.isOverflow) {
233
+ if (!this.scroller) {
234
+ this.scroller = new Scroller(this);
235
+ if (!this.topChildren) this.topChildren = [];
236
+ this.topChildren.push(this.scroller);
237
+ }
238
+ this.hasScroller = true;
239
+ } else {
240
+ if (this.hasScroller && !this.scroller.dragScrolling) {
241
+ this.hasScroller = undefined;
242
+ this.scroller.update();
243
+ }
244
+ }
245
+ };
246
+
247
+ Scroller.registerTheme("light", {
248
+ style: {
249
+ fill: "black"
250
+ }
251
+ });
252
+
253
+ Scroller.registerTheme("dark", {
254
+ style: {
255
+ fill: "white"
256
+ }
257
+ });
258
+
259
+ exports.Scroller = Scroller;
@@ -0,0 +1,257 @@
1
+ import { Bounds, MathHelper, DataHelper, Group, Box, isUndefined, LeafHelper, BranchHelper, DragBoundsHelper, Plugin, DragEvent, PointerEvent, MoveEvent, BoundsEvent, ChildEvent, decorateLeafAttr, attr, doBoundsType } from "@leafer-ui/core";
2
+
3
+ const config = {
4
+ theme: "light",
5
+ style: {
6
+ dragBoundsType: "outer",
7
+ strokeAlign: "center",
8
+ strokeWidthFixed: "zoom-in",
9
+ width: 6,
10
+ height: 6,
11
+ opacity: .5,
12
+ cornerRadius: 3,
13
+ hoverStyle: {
14
+ opacity: .6
15
+ },
16
+ pressStyle: {
17
+ opacity: .66
18
+ }
19
+ },
20
+ size: 6,
21
+ endsMargin: 2,
22
+ sideMargin: 2,
23
+ minSize: 10,
24
+ scaleFixed: "zoom-in",
25
+ scrollType: "both",
26
+ hideOnActionEnd: "hover"
27
+ };
28
+
29
+ const tempBounds = new Bounds, {float: float} = MathHelper, {clone: clone, assign: assign} = DataHelper;
30
+
31
+ class Scroller extends Group {
32
+ get canUse() {
33
+ return this.target.hasScroller;
34
+ }
35
+ constructor(target) {
36
+ super();
37
+ this.targetWorldBounds = new Bounds;
38
+ this.viewportBounds = new Bounds;
39
+ this.contentBounds = new Bounds;
40
+ this.scrollXBounds = new Bounds;
41
+ this.scrollYBounds = new Bounds;
42
+ this.target = target;
43
+ this.config = clone(config);
44
+ this.updateConfig();
45
+ this.__listenEvents();
46
+ target.waitLeafer(() => {
47
+ this.parent = target;
48
+ this.__bindLeafer(target.leafer);
49
+ });
50
+ if (this.mergedConfig.hideOnActionEnd) this.opacity = 0;
51
+ }
52
+ static registerTheme(theme, themeConfig) {
53
+ S.themeMap[theme] = themeConfig;
54
+ }
55
+ static getTheme(theme) {
56
+ return theme && S.themeMap[theme];
57
+ }
58
+ static hasTheme(theme) {
59
+ return theme && !!S.themeMap[theme];
60
+ }
61
+ updateConfig() {
62
+ const {scrollConfig: scrollConfig} = this.target;
63
+ const themeConfig = S.getTheme(scrollConfig && S.hasTheme(scrollConfig.theme) && scrollConfig.theme || this.config.theme);
64
+ const mergedConfig = this.mergedConfig = clone(this.config);
65
+ assign(mergedConfig, themeConfig);
66
+ if (scrollConfig) assign(mergedConfig, scrollConfig);
67
+ this.updateStyle(mergedConfig.style);
68
+ }
69
+ updateStyle(style) {
70
+ if (!this.scrollXBar) this.addMany(this.scrollXBar = new Box, this.scrollYBar = new Box);
71
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar} = this;
72
+ scrollXBar.set(style);
73
+ scrollYBar.set(style);
74
+ scrollXBar.draggable = "x";
75
+ scrollYBar.draggable = "y";
76
+ }
77
+ update(check = true) {
78
+ if (this.dragScrolling) return;
79
+ const {target: target, targetOverflow: targetOverflow, targetWorldBounds: targetWorldBounds, viewportBounds: viewportBounds, contentBounds: contentBounds} = this, layout = target.__layout, {overflow: overflow} = target.__;
80
+ const {childrenRenderBounds: childrenRenderBounds} = layout;
81
+ const {boxBounds: boxBounds, worldBoxBounds: worldBoxBounds} = layout;
82
+ const isSameWorldBounds = check && targetOverflow === overflow && targetWorldBounds.isSame(worldBoxBounds);
83
+ const isSameConfig = layout.scrollConfigChanged ? (this.updateConfig(), layout.scrollConfigChanged = false) : true;
84
+ const nowContentBounds = tempBounds.set(viewportBounds).add(childrenRenderBounds);
85
+ if (isSameWorldBounds && isSameConfig && contentBounds.isSame(nowContentBounds)) return;
86
+ this.targetOverflow = overflow;
87
+ viewportBounds.set(boxBounds);
88
+ targetWorldBounds.set(worldBoxBounds);
89
+ contentBounds.set(nowContentBounds);
90
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar} = this, {size: size, endsMargin: endsMargin, minSize: minSize} = this.mergedConfig, {width: width, height: height} = viewportBounds;
91
+ this.contentRealX = contentBounds.x - target.scrollX;
92
+ this.contentRealY = contentBounds.y - target.scrollY;
93
+ this.ratioX = viewportBounds.width / contentBounds.width;
94
+ this.ratioY = viewportBounds.height / contentBounds.height;
95
+ const min = size + endsMargin * 2 + minSize;
96
+ scrollXBar.visible = float(contentBounds.width) > float(width) && overflow !== "y-scroll" && width > min;
97
+ scrollYBar.visible = float(contentBounds.height) > float(height) && overflow !== "x-scroll" && height > min;
98
+ this.updateScrollBar();
99
+ }
100
+ updateScrollBar() {
101
+ const {target: target, viewportBounds: viewportBounds, contentBounds: contentBounds, ratioX: ratioX, ratioY: ratioY, scrollXBar: scrollXBar, scrollYBar: scrollYBar, scrollXBounds: scrollXBounds, scrollYBounds: scrollYBounds} = this;
102
+ let {size: size, cornerRadius: cornerRadius, endsMargin: endsMargin, sideMargin: sideMargin, minSize: minSize, scaleFixed: scaleFixed, scrollType: scrollType} = this.mergedConfig;
103
+ const scale = scaleFixed ? target.getClampRenderScale() : 1;
104
+ endsMargin /= scale;
105
+ sideMargin /= scale;
106
+ size /= scale;
107
+ if (isUndefined(cornerRadius)) cornerRadius = size / 2;
108
+ if (scrollXBar.visible) {
109
+ scrollXBounds.set(viewportBounds).shrink([ endsMargin, scrollYBar.visible ? size + sideMargin : endsMargin, sideMargin, endsMargin ]);
110
+ const scrollRatioX = this.scrollRatioX = scrollXBounds.width / contentBounds.width;
111
+ scrollXBar.set({
112
+ x: scrollXBounds.x - contentBounds.x * scrollRatioX,
113
+ y: scrollXBounds.maxY - size,
114
+ width: Math.max(scrollXBounds.width * ratioX, minSize),
115
+ height: size,
116
+ cornerRadius: cornerRadius,
117
+ dragBounds: scrollXBounds,
118
+ hittable: scrollType !== "move"
119
+ });
120
+ }
121
+ if (scrollYBar.visible) {
122
+ scrollYBounds.set(viewportBounds).shrink([ endsMargin, sideMargin, scrollXBar.visible ? size + sideMargin : endsMargin, endsMargin ]);
123
+ const scrollRatioY = this.scrollRatioY = scrollYBounds.height / contentBounds.height;
124
+ scrollYBar.set({
125
+ x: scrollYBounds.maxX - size,
126
+ y: scrollYBounds.y - contentBounds.y * scrollRatioY,
127
+ width: size,
128
+ height: Math.max(scrollYBounds.height * ratioY, minSize),
129
+ cornerRadius: cornerRadius,
130
+ dragBounds: scrollYBounds,
131
+ hittable: scrollType !== "move"
132
+ });
133
+ }
134
+ this.x = -this.target.scrollX;
135
+ this.y = -this.target.scrollY;
136
+ LeafHelper.updateAllMatrix(this);
137
+ BranchHelper.updateBounds(this);
138
+ LeafHelper.updateAllChange(this);
139
+ }
140
+ onDrag(e) {
141
+ if (this.mergedConfig.scrollType === "move") return;
142
+ this.dragScrolling = true;
143
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar, target: target, scrollXBounds: scrollXBounds, scrollYBounds: scrollYBounds} = this;
144
+ const scrollX = e.current === scrollXBar;
145
+ if (scrollX) target.scrollX = -((scrollXBar.x - scrollXBounds.x) / this.scrollRatioX + this.contentRealX); else target.scrollY = -((scrollYBar.y - scrollYBounds.y) / this.scrollRatioY + this.contentRealY);
146
+ }
147
+ onDragEnd() {
148
+ if (this.mergedConfig.scrollType === "move") return;
149
+ this.dragScrolling = false;
150
+ }
151
+ onMove(e) {
152
+ if (!this.canUse) return;
153
+ this.onEnter();
154
+ const {scrollType: scrollType, stopDefault: stopDefault} = this.mergedConfig;
155
+ if (scrollType === "drag") return;
156
+ const {viewportBounds: viewportBounds, contentBounds: contentBounds, scrollXBar: scrollXBar, scrollYBar: scrollYBar} = this;
157
+ if (scrollXBar.visible || scrollYBar.visible) {
158
+ const move = e.getInnerMove(this.target);
159
+ DragBoundsHelper.getValidMove(contentBounds, viewportBounds, "inner", move, true);
160
+ let needStop;
161
+ if (move.x && scrollXBar.visible) this.target.scrollX += move.x, needStop = true;
162
+ if (move.y && scrollYBar.visible) this.target.scrollY += move.y, needStop = true;
163
+ if (needStop || stopDefault) e.stop();
164
+ if (stopDefault) e.stopDefault();
165
+ }
166
+ }
167
+ onMoveEnd(e) {
168
+ if (!this.canUse) return;
169
+ if (!this.target.hit(e)) this.onLeave();
170
+ }
171
+ onEnter() {
172
+ if (!this.canUse) return;
173
+ clearTimeout(this.hideTimer);
174
+ this.killAnimate();
175
+ this.opacity = 1;
176
+ }
177
+ onLeave() {
178
+ if (!this.canUse) return;
179
+ clearTimeout(this.hideTimer);
180
+ if (this.mergedConfig.hideOnActionEnd) this.hideTimer = setTimeout(() => {
181
+ this.set({
182
+ opacity: 0
183
+ }, Plugin.has("animate"));
184
+ }, 600);
185
+ }
186
+ onResize() {
187
+ if (this.canUse) this.update();
188
+ }
189
+ __listenEvents() {
190
+ const {scrollXBar: scrollXBar, scrollYBar: scrollYBar, target: target} = this;
191
+ this.__eventIds = [ scrollXBar.on_(DragEvent.DRAG, this.onDrag, this), scrollXBar.on_(DragEvent.END, this.onDragEnd, this), scrollYBar.on_(DragEvent.DRAG, this.onDrag, this), scrollYBar.on_(DragEvent.END, this.onDragEnd, this), target.on_(PointerEvent.ENTER, this.onEnter, this), target.on_(PointerEvent.LEAVE, this.onLeave, this), target.on_(MoveEvent.BEFORE_MOVE, this.onMove, this), target.on_(MoveEvent.END, this.onMoveEnd, this), target.on_(BoundsEvent.WORLD, this.onResize, this), target.on_(ChildEvent.DESTROY, this.destroy, this) ];
192
+ }
193
+ __removeListenEvents() {
194
+ this.off_(this.__eventIds);
195
+ }
196
+ destroy() {
197
+ if (!this.destroyed) {
198
+ this.__removeListenEvents();
199
+ const {target: target} = this;
200
+ target.scroller = target.topChildren = target.hasScroller = undefined;
201
+ this.target = this.config = null;
202
+ super.destroy();
203
+ }
204
+ }
205
+ }
206
+
207
+ Scroller.themeMap = {};
208
+
209
+ const S = Scroller;
210
+
211
+ function scrollConfigType(defaultValue) {
212
+ return decorateLeafAttr(defaultValue, key => attr({
213
+ set(value) {
214
+ if (this.__setAttr(key, value)) {
215
+ const layout = this.__layout;
216
+ layout.scrollConfigChanged = true;
217
+ doBoundsType(this);
218
+ }
219
+ }
220
+ }));
221
+ }
222
+
223
+ Plugin.add("scroller");
224
+
225
+ const box = Box.prototype;
226
+
227
+ Box.addAttr("scrollConfig", undefined, scrollConfigType);
228
+
229
+ box.__checkScroll = function(isScrollMode) {
230
+ if (isScrollMode && this.isOverflow) {
231
+ if (!this.scroller) {
232
+ this.scroller = new Scroller(this);
233
+ if (!this.topChildren) this.topChildren = [];
234
+ this.topChildren.push(this.scroller);
235
+ }
236
+ this.hasScroller = true;
237
+ } else {
238
+ if (this.hasScroller && !this.scroller.dragScrolling) {
239
+ this.hasScroller = undefined;
240
+ this.scroller.update();
241
+ }
242
+ }
243
+ };
244
+
245
+ Scroller.registerTheme("light", {
246
+ style: {
247
+ fill: "black"
248
+ }
249
+ });
250
+
251
+ Scroller.registerTheme("dark", {
252
+ style: {
253
+ fill: "white"
254
+ }
255
+ });
256
+
257
+ export { Scroller };
@@ -0,0 +1,2 @@
1
+ import{Bounds as t,MathHelper as e,DataHelper as s,Group as i,Box as o,isUndefined as r,LeafHelper as n,BranchHelper as h,DragBoundsHelper as l,Plugin as a,DragEvent as c,PointerEvent as d,MoveEvent as g,BoundsEvent as u,ChildEvent as m,decorateLeafAttr as p,attr as f,doBoundsType as v}from"@leafer-ui/core";const B={theme:"light",style:{dragBoundsType:"outer",strokeAlign:"center",strokeWidthFixed:"zoom-in",width:6,height:6,opacity:.5,cornerRadius:3,hoverStyle:{opacity:.6},pressStyle:{opacity:.66}},size:6,endsMargin:2,sideMargin:2,minSize:10,scaleFixed:"zoom-in",scrollType:"both",hideOnActionEnd:"hover"},y=new t,{float:_}=e,{clone:w,assign:E}=s;class C extends i{get canUse(){return this.target.hasScroller}constructor(e){super(),this.targetWorldBounds=new t,this.viewportBounds=new t,this.contentBounds=new t,this.scrollXBounds=new t,this.scrollYBounds=new t,this.target=e,this.config=w(B),this.updateConfig(),this.__listenEvents(),e.waitLeafer(()=>{this.parent=e,this.__bindLeafer(e.leafer)}),this.mergedConfig.hideOnActionEnd&&(this.opacity=0)}static registerTheme(t,e){x.themeMap[t]=e}static getTheme(t){return t&&x.themeMap[t]}static hasTheme(t){return t&&!!x.themeMap[t]}updateConfig(){const{scrollConfig:t}=this.target,e=x.getTheme(t&&x.hasTheme(t.theme)&&t.theme||this.config.theme),s=this.mergedConfig=w(this.config);E(s,e),t&&E(s,t),this.updateStyle(s.style)}updateStyle(t){this.scrollXBar||this.addMany(this.scrollXBar=new o,this.scrollYBar=new o);const{scrollXBar:e,scrollYBar:s}=this;e.set(t),s.set(t),e.draggable="x",s.draggable="y"}update(t=!0){if(this.dragScrolling)return;const{target:e,targetOverflow:s,targetWorldBounds:i,viewportBounds:o,contentBounds:r}=this,n=e.__layout,{overflow:h}=e.__,{childrenRenderBounds:l}=n,{boxBounds:a,worldBoxBounds:c}=n,d=t&&s===h&&i.isSame(c),g=!n.scrollConfigChanged||(this.updateConfig(),n.scrollConfigChanged=!1),u=y.set(o).add(l);if(d&&g&&r.isSame(u))return;this.targetOverflow=h,o.set(a),i.set(c),r.set(u);const{scrollXBar:m,scrollYBar:p}=this,{size:f,endsMargin:v,minSize:B}=this.mergedConfig,{width:w,height:E}=o;this.contentRealX=r.x-e.scrollX,this.contentRealY=r.y-e.scrollY,this.ratioX=o.width/r.width,this.ratioY=o.height/r.height;const C=f+2*v+B;m.visible=_(r.width)>_(w)&&"y-scroll"!==h&&w>C,p.visible=_(r.height)>_(E)&&"x-scroll"!==h&&E>C,this.updateScrollBar()}updateScrollBar(){const{target:t,viewportBounds:e,contentBounds:s,ratioX:i,ratioY:o,scrollXBar:l,scrollYBar:a,scrollXBounds:c,scrollYBounds:d}=this;let{size:g,cornerRadius:u,endsMargin:m,sideMargin:p,minSize:f,scaleFixed:v,scrollType:B}=this.mergedConfig;const y=v?t.getClampRenderScale():1;if(m/=y,p/=y,g/=y,r(u)&&(u=g/2),l.visible){c.set(e).shrink([m,a.visible?g+p:m,p,m]);const t=this.scrollRatioX=c.width/s.width;l.set({x:c.x-s.x*t,y:c.maxY-g,width:Math.max(c.width*i,f),height:g,cornerRadius:u,dragBounds:c,hittable:"move"!==B})}if(a.visible){d.set(e).shrink([m,p,l.visible?g+p:m,m]);const t=this.scrollRatioY=d.height/s.height;a.set({x:d.maxX-g,y:d.y-s.y*t,width:g,height:Math.max(d.height*o,f),cornerRadius:u,dragBounds:d,hittable:"move"!==B})}this.x=-this.target.scrollX,this.y=-this.target.scrollY,n.updateAllMatrix(this),h.updateBounds(this),n.updateAllChange(this)}onDrag(t){if("move"===this.mergedConfig.scrollType)return;this.dragScrolling=!0;const{scrollXBar:e,scrollYBar:s,target:i,scrollXBounds:o,scrollYBounds:r}=this;t.current===e?i.scrollX=-((e.x-o.x)/this.scrollRatioX+this.contentRealX):i.scrollY=-((s.y-r.y)/this.scrollRatioY+this.contentRealY)}onDragEnd(){"move"!==this.mergedConfig.scrollType&&(this.dragScrolling=!1)}onMove(t){if(!this.canUse)return;this.onEnter();const{scrollType:e,stopDefault:s}=this.mergedConfig;if("drag"===e)return;const{viewportBounds:i,contentBounds:o,scrollXBar:r,scrollYBar:n}=this;if(r.visible||n.visible){const e=t.getInnerMove(this.target);let h;l.getValidMove(o,i,"inner",e,!0),e.x&&r.visible&&(this.target.scrollX+=e.x,h=!0),e.y&&n.visible&&(this.target.scrollY+=e.y,h=!0),(h||s)&&t.stop(),s&&t.stopDefault()}}onMoveEnd(t){this.canUse&&(this.target.hit(t)||this.onLeave())}onEnter(){this.canUse&&(clearTimeout(this.hideTimer),this.killAnimate(),this.opacity=1)}onLeave(){this.canUse&&(clearTimeout(this.hideTimer),this.mergedConfig.hideOnActionEnd&&(this.hideTimer=setTimeout(()=>{this.set({opacity:0},a.has("animate"))},600)))}onResize(){this.canUse&&this.update()}__listenEvents(){const{scrollXBar:t,scrollYBar:e,target:s}=this;this.__eventIds=[t.on_(c.DRAG,this.onDrag,this),t.on_(c.END,this.onDragEnd,this),e.on_(c.DRAG,this.onDrag,this),e.on_(c.END,this.onDragEnd,this),s.on_(d.ENTER,this.onEnter,this),s.on_(d.LEAVE,this.onLeave,this),s.on_(g.BEFORE_MOVE,this.onMove,this),s.on_(g.END,this.onMoveEnd,this),s.on_(u.WORLD,this.onResize,this),s.on_(m.DESTROY,this.destroy,this)]}__removeListenEvents(){this.off_(this.__eventIds)}destroy(){if(!this.destroyed){this.__removeListenEvents();const{target:t}=this;t.scroller=t.topChildren=t.hasScroller=void 0,this.target=this.config=null,super.destroy()}}}C.themeMap={};const x=C;a.add("scroller");const S=o.prototype;o.addAttr("scrollConfig",void 0,function(t){return p(t,t=>f({set(e){if(this.__setAttr(t,e)){this.__layout.scrollConfigChanged=!0,v(this)}}}))}),S.__checkScroll=function(t){t&&this.isOverflow?(this.scroller||(this.scroller=new C(this),this.topChildren||(this.topChildren=[]),this.topChildren.push(this.scroller)),this.hasScroller=!0):this.hasScroller&&!this.scroller.dragScrolling&&(this.hasScroller=void 0,this.scroller.update())},C.registerTheme("light",{style:{fill:"black"}}),C.registerTheme("dark",{style:{fill:"white"}});export{C as Scroller};
2
+ //# sourceMappingURL=scroller.esm.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroller.esm.min.js","sources":["../../../../../../src/preview/packages/scroller/src/config.ts","../../../../../../src/preview/packages/scroller/src/Scroller.ts","../../../../../../src/preview/packages/scroller/src/index.ts","../../../../../../src/preview/packages/scroller/src/decorate.ts"],"sourcesContent":["import { IScrollConfig } from '@leafer-ui/interface'\n\n\nexport const config: IScrollConfig = {\n theme: 'light',\n style: { dragBoundsType: 'outer', strokeAlign: 'center', strokeWidthFixed: 'zoom-in', width: 6, height: 6, opacity: 0.5, cornerRadius: 3, hoverStyle: { opacity: 0.6 }, pressStyle: { opacity: 0.66 } },\n size: 6,\n endsMargin: 2,\n sideMargin: 2,\n minSize: 10,\n scaleFixed: 'zoom-in',\n scrollType: 'both',\n hideOnActionEnd: 'hover'\n}\n\n","import { IBounds, IBox, IBoxInputData, IEventListenerId, IOverflow, IScroller, IScrollConfig, IScrollTheme, IObject } from '@leafer-ui/interface'\nimport { Group, Box, Bounds, DataHelper, DragEvent, LeafHelper, MoveEvent, DragBoundsHelper, ChildEvent, PointerEvent, Plugin, MathHelper, BranchHelper, isUndefined, BoundsEvent } from '@leafer-ui/core'\n\nimport { config } from './config'\n\n\nconst tempBounds = new Bounds(), { float } = MathHelper, { clone, assign } = DataHelper\n\nexport class Scroller extends Group implements IScroller {\n\n // 主题 map\n static themeMap: IObject = {}\n\n\n public target: IBox\n\n public config: IScrollConfig\n public mergedConfig: IScrollConfig\n\n public scrollXBar: IBox\n public scrollYBar: IBox\n\n // viewport 区域 / 内容区域\n public ratioX: number\n public ratioY: number\n\n // 滚动区域 / 内容区域\n public scrollRatioX: number\n public scrollRatioY: number\n\n // scroll之前的内容真实定位\n public contentRealX: number\n public contentRealY: number\n\n public dragScrolling: boolean\n\n // 用于比对数据,节流\n public targetOverflow: IOverflow\n public targetWorldBounds: IBounds = new Bounds()\n\n // viewport 与 内容区域\n public viewportBounds: IBounds = new Bounds()\n public contentBounds: IBounds = new Bounds()\n\n // 相对 viewport 区域收缩了一点边距\n public scrollXBounds: IBounds = new Bounds()\n public scrollYBounds: IBounds = new Bounds()\n\n\n protected get canUse(): boolean { return this.target.hasScroller }\n\n protected hideTimer: any\n\n protected __eventIds: IEventListenerId[]\n\n constructor(target: IBox) {\n super()\n this.target = target\n this.config = clone(config)\n this.updateConfig()\n this.__listenEvents()\n\n target.waitLeafer(() => {\n this.parent = target\n this.__bindLeafer(target.leafer)\n })\n\n if (this.mergedConfig.hideOnActionEnd) this.opacity = 0\n }\n\n\n static registerTheme(theme: IScrollTheme, themeConfig: IScrollConfig): void {\n S.themeMap[theme] = themeConfig\n }\n\n static getTheme(theme: IScrollTheme): IScrollConfig {\n return theme && S.themeMap[theme]\n }\n\n static hasTheme(theme: IScrollTheme): boolean {\n return theme && !!S.themeMap[theme]\n }\n\n\n public updateConfig(): void {\n const { scrollConfig } = this.target\n const themeConfig = S.getTheme((scrollConfig && S.hasTheme(scrollConfig.theme) && scrollConfig.theme) || this.config.theme)\n const mergedConfig: IScrollConfig = this.mergedConfig = clone(this.config)\n assign(mergedConfig, themeConfig)\n if (scrollConfig) assign(mergedConfig, scrollConfig)\n this.updateStyle(mergedConfig.style)\n }\n\n public updateStyle(style: IBoxInputData): void {\n if (!this.scrollXBar) this.addMany(this.scrollXBar = new Box(), this.scrollYBar = new Box())\n const { scrollXBar, scrollYBar } = this\n scrollXBar.set(style)\n scrollYBar.set(style)\n scrollXBar.draggable = 'x'\n scrollYBar.draggable = 'y'\n }\n\n public update(check: boolean = true): void {\n if (this.dragScrolling) return\n\n const { target, targetOverflow, targetWorldBounds, viewportBounds, contentBounds } = this, layout = target.__layout, { overflow } = target.__\n\n const { childrenRenderBounds } = layout // 内容 bounds\n const { boxBounds, worldBoxBounds } = layout // 容器 bounds\n\n const isSameWorldBounds = check && targetOverflow === overflow && targetWorldBounds.isSame(worldBoxBounds)\n const isSameConfig = layout.scrollConfigChanged ? (this.updateConfig(), layout.scrollConfigChanged = false) : true\n\n const nowContentBounds = tempBounds.set(viewportBounds).add(childrenRenderBounds)\n\n if (isSameWorldBounds && isSameConfig && contentBounds.isSame(nowContentBounds)) return // 节流\n\n this.targetOverflow = overflow\n viewportBounds.set(boxBounds)\n targetWorldBounds.set(worldBoxBounds)\n contentBounds.set(nowContentBounds)\n\n const { scrollXBar, scrollYBar } = this, { size, endsMargin, minSize } = this.mergedConfig, { width, height } = viewportBounds\n\n this.contentRealX = contentBounds.x - target.scrollX\n this.contentRealY = contentBounds.y - target.scrollY\n\n this.ratioX = viewportBounds.width / contentBounds.width\n this.ratioY = viewportBounds.height / contentBounds.height\n\n const min = size + endsMargin * 2 + minSize\n scrollXBar.visible = float(contentBounds.width) > float(width) && overflow !== 'y-scroll' && width > min\n scrollYBar.visible = float(contentBounds.height) > float(height) && overflow !== 'x-scroll' && height > min\n\n this.updateScrollBar()\n }\n\n public updateScrollBar() {\n const { target, viewportBounds, contentBounds, ratioX, ratioY, scrollXBar, scrollYBar, scrollXBounds, scrollYBounds } = this\n let { size, cornerRadius, endsMargin, sideMargin, minSize, scaleFixed, scrollType } = this.mergedConfig\n const scale = scaleFixed ? target.getClampRenderScale() : 1\n\n endsMargin /= scale\n sideMargin /= scale\n size /= scale\n if (isUndefined(cornerRadius)) cornerRadius = size / 2\n\n if (scrollXBar.visible) {\n scrollXBounds.set(viewportBounds).shrink([endsMargin, scrollYBar.visible ? size + sideMargin : endsMargin, sideMargin, endsMargin])\n const scrollRatioX = this.scrollRatioX = scrollXBounds.width / contentBounds.width\n\n scrollXBar.set({\n x: scrollXBounds.x - contentBounds.x * scrollRatioX,\n y: scrollXBounds.maxY - size,\n width: Math.max(scrollXBounds.width * ratioX, minSize),\n height: size,\n cornerRadius,\n dragBounds: scrollXBounds,\n hittable: scrollType !== 'move'\n })\n }\n\n if (scrollYBar.visible) {\n scrollYBounds.set(viewportBounds).shrink([endsMargin, sideMargin, scrollXBar.visible ? size + sideMargin : endsMargin, endsMargin])\n const scrollRatioY = this.scrollRatioY = scrollYBounds.height / contentBounds.height\n\n scrollYBar.set({\n x: scrollYBounds.maxX - size,\n y: scrollYBounds.y - contentBounds.y * scrollRatioY,\n width: size,\n height: Math.max(scrollYBounds.height * ratioY, minSize),\n cornerRadius,\n dragBounds: scrollYBounds,\n hittable: scrollType !== 'move'\n })\n }\n\n this.x = -this.target.scrollX\n this.y = -this.target.scrollY\n\n LeafHelper.updateAllMatrix(this)\n BranchHelper.updateBounds(this)\n LeafHelper.updateAllChange(this)\n }\n\n protected onDrag(e: DragEvent): void {\n if (this.mergedConfig.scrollType === 'move') return\n\n this.dragScrolling = true\n\n const { scrollXBar, scrollYBar, target, scrollXBounds, scrollYBounds } = this\n const scrollX = e.current === scrollXBar\n\n if (scrollX) target.scrollX = -((scrollXBar.x - scrollXBounds.x) / this.scrollRatioX + this.contentRealX)\n else target.scrollY = -((scrollYBar.y - scrollYBounds.y) / this.scrollRatioY + this.contentRealY)\n }\n\n protected onDragEnd(): void {\n if (this.mergedConfig.scrollType === 'move') return\n\n this.dragScrolling = false\n }\n\n protected onMove(e: MoveEvent): void {\n if (!this.canUse) return\n\n this.onEnter()\n\n const { scrollType, stopDefault } = this.mergedConfig\n if (scrollType === 'drag') return\n\n const { viewportBounds, contentBounds, scrollXBar, scrollYBar } = this\n if (scrollXBar.visible || scrollYBar.visible) {\n const move = e.getInnerMove(this.target)\n DragBoundsHelper.getValidMove(contentBounds, viewportBounds, 'inner', move, true)\n\n let needStop: boolean\n if (move.x && scrollXBar.visible) this.target.scrollX += move.x, needStop = true\n if (move.y && scrollYBar.visible) this.target.scrollY += move.y, needStop = true\n if (needStop || stopDefault) e.stop()\n if (stopDefault) e.stopDefault()\n }\n }\n\n protected onMoveEnd(e: MoveEvent): void {\n if (!this.canUse) return\n\n if (!this.target.hit(e)) this.onLeave()\n }\n\n protected onEnter() {\n if (!this.canUse) return\n\n clearTimeout(this.hideTimer)\n\n this.killAnimate()\n this.opacity = 1\n }\n\n protected onLeave() {\n if (!this.canUse) return\n\n clearTimeout(this.hideTimer)\n\n if (this.mergedConfig.hideOnActionEnd) this.hideTimer = setTimeout(() => {\n this.set({ opacity: 0 }, Plugin.has('animate'))\n }, 600)\n }\n\n protected onResize() {\n if (this.canUse) this.update()\n }\n\n protected __listenEvents(): void {\n const { scrollXBar, scrollYBar, target } = this\n this.__eventIds = [\n scrollXBar.on_(DragEvent.DRAG, this.onDrag, this),\n scrollXBar.on_(DragEvent.END, this.onDragEnd, this),\n\n scrollYBar.on_(DragEvent.DRAG, this.onDrag, this),\n scrollYBar.on_(DragEvent.END, this.onDragEnd, this),\n\n target.on_(PointerEvent.ENTER, this.onEnter, this),\n target.on_(PointerEvent.LEAVE, this.onLeave, this),\n\n target.on_(MoveEvent.BEFORE_MOVE, this.onMove, this),\n target.on_(MoveEvent.END, this.onMoveEnd, this),\n\n target.on_(BoundsEvent.WORLD, this.onResize, this), // 更新\n target.on_(ChildEvent.DESTROY, this.destroy, this)\n ]\n }\n\n protected __removeListenEvents(): void {\n this.off_(this.__eventIds)\n }\n\n public destroy(): void {\n if (!this.destroyed) {\n this.__removeListenEvents()\n const { target } = this\n target.scroller = target.topChildren = target.hasScroller = undefined\n this.target = this.config = null\n super.destroy()\n }\n }\n\n}\n\nconst S = Scroller","export { Scroller } from './Scroller'\n\nimport { Plugin, Box } from '@leafer-ui/core'\nimport { Scroller } from './Scroller'\nimport { scrollConfigType } from './decorate'\n\n\nPlugin.add('scroller')\n\n\nconst box = Box.prototype\n\nBox.addAttr('scrollConfig', undefined, scrollConfigType)\n\nbox.__checkScroll = function (isScrollMode: boolean) {\n if (isScrollMode && this.isOverflow) {\n if (!this.scroller) {\n this.scroller = new Scroller(this)\n if (!this.topChildren) this.topChildren = []\n this.topChildren.push(this.scroller)\n }\n this.hasScroller = true\n } else {\n if (this.hasScroller && !this.scroller.dragScrolling) {\n this.hasScroller = undefined\n this.scroller.update()\n }\n }\n}\n\nScroller.registerTheme('light', { style: { fill: 'black' } }) // 白天模式\nScroller.registerTheme('dark', { style: { fill: 'white' } }) // 夜间模式","import { IValue } from '@leafer-ui/interface'\nimport { decorateLeafAttr, attr, doBoundsType } from '@leafer-ui/core'\n\n\nexport function scrollConfigType(defaultValue?: IValue) {\n return decorateLeafAttr(defaultValue, (key: string) => attr({\n set(value: IValue) {\n if (this.__setAttr(key, value)) {\n const layout = this.__layout\n layout.scrollConfigChanged = true\n doBoundsType(this)\n }\n }\n }))\n}\n"],"names":["config","theme","style","dragBoundsType","strokeAlign","strokeWidthFixed","width","height","opacity","cornerRadius","hoverStyle","pressStyle","size","endsMargin","sideMargin","minSize","scaleFixed","scrollType","hideOnActionEnd","tempBounds","Bounds","float","MathHelper","clone","assign","DataHelper","Scroller","Group","canUse","this","target","hasScroller","constructor","super","targetWorldBounds","viewportBounds","contentBounds","scrollXBounds","scrollYBounds","updateConfig","__listenEvents","waitLeafer","parent","__bindLeafer","leafer","mergedConfig","registerTheme","themeConfig","S","themeMap","getTheme","hasTheme","scrollConfig","updateStyle","scrollXBar","addMany","Box","scrollYBar","set","draggable","update","check","dragScrolling","targetOverflow","layout","__layout","overflow","__","childrenRenderBounds","boxBounds","worldBoxBounds","isSameWorldBounds","isSame","isSameConfig","scrollConfigChanged","nowContentBounds","add","contentRealX","x","scrollX","contentRealY","y","scrollY","ratioX","ratioY","min","visible","updateScrollBar","scale","getClampRenderScale","isUndefined","shrink","scrollRatioX","maxY","Math","max","dragBounds","hittable","scrollRatioY","maxX","LeafHelper","updateAllMatrix","BranchHelper","updateBounds","updateAllChange","onDrag","e","current","onDragEnd","onMove","onEnter","stopDefault","move","getInnerMove","needStop","DragBoundsHelper","getValidMove","stop","onMoveEnd","hit","onLeave","clearTimeout","hideTimer","killAnimate","setTimeout","Plugin","has","onResize","__eventIds","on_","DragEvent","DRAG","END","PointerEvent","ENTER","LEAVE","MoveEvent","BEFORE_MOVE","BoundsEvent","WORLD","ChildEvent","DESTROY","destroy","__removeListenEvents","off_","destroyed","scroller","topChildren","undefined","box","prototype","addAttr","defaultValue","decorateLeafAttr","key","attr","value","__setAttr","doBoundsType","__checkScroll","isScrollMode","isOverflow","push","fill"],"mappings":"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"}