├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── dist
└── index.wxs
├── example
├── .gitignore
├── app.js
├── app.json
├── app.wxss
├── pages
│ ├── dynamic
│ │ ├── index.js
│ │ ├── index.json
│ │ └── index.wxml
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ └── index.wxml
│ ├── multiple
│ │ ├── comp1
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── comp2
│ │ │ ├── index.js
│ │ │ ├── index.json
│ │ │ └── index.wxml
│ │ ├── index.js
│ │ ├── index.json
│ │ └── index.wxml
│ └── vertical
│ │ ├── index.js
│ │ ├── index.json
│ │ └── index.wxml
├── project.config.json
├── sitemap.json
└── weapp-scroll.wxs
├── package-lock.json
├── package.json
├── preview.gif
├── rollup.config.js
├── src
├── Easing.ts
├── Utils.ts
├── core.ts
├── index.ts
├── options.ts
└── wxs.d.ts
└── tsconfig.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.wxs linguist-language=js
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Xieyuhang
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 all
13 | 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 THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Weapp Scroll
2 | Weapp Scroll 是基于 [WXS](https://developers.weixin.qq.com/miniprogram/dev/reference/wxs/01wxs-module.html) 实现的平滑滚动容器,有一些计算的逻辑参考了 [better-scroll](https://github.com/ustbhuangyi/better-scroll)。
3 |
4 | 在微信小程序中,使用 WXS 相对于逻辑层来处理交互事件拥有较好的性能,相关官方文档:[WXS响应事件](https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html)。
5 |
6 | [微信小程序中基于WXS实现回弹的平滑滚动容器](https://juejin.cn/post/7119278260315242503)
7 |
8 | ## 效果预览
9 |
10 |
11 | ## 使用
12 | 1. 拷贝 `dist/index.wxs` 文件至项目中并重命名为 `weapp-scroll.wxs`
13 | 2. 在需要使用的页面或组件使用 `` 标签引入 `weapp-scroll.wxs`
14 |
15 | 下面是创建横向滚动的简单的示例:
16 |
17 | ```html
18 |
19 |
20 |
21 |
30 |
31 | {{ item }}
32 |
33 |
34 | ```
35 |
36 | ## 示例
37 | 项目中 example 目录是一个小程序项目,里面包含了一些使用示例
38 |
39 | + `example/pages/index`,横向滚动
40 | + `example/pages/vertical`,竖向滚动
41 | + `example/pages/dynamic`,容器子元素动态变化
42 | + `example/pages/multiple`,同一页面使用多次
43 |
44 | ## 选项
45 |
46 | | 属性 | 默认值 | 描述 |
47 | | ------------------------ | ------------------------------------------------- | ------------------------------------------------------------ |
48 | | enableScrollX | 滑动容器的宽度大于容器的宽度时为 true,否则 false | 是否启用横向的滚动 |
49 | | enableScrollY | 滑动容器的高度大于容器的高度时为 true,否则 false | 是否启用竖向的滚动 |
50 | | slidingContainerSelector | .content | 滑动容器的选择器 |
51 | | damping | 0.3 | 滑动超出边界后,超出边界的阻尼系数,取值在 [0, 1],值约小,阻力越大 |
52 | | bounceDuration | 800 | 滑动超出边界后进行反弹,设置反弹动画的持续时间 |
53 |
54 | ## 事件
55 | ### onScroll
56 | 在滑动容器滑动时触发
57 | ```ts
58 | interface ScrollCallback {
59 | (data: {
60 | // 滑动容器的 translateX
61 | x: number
62 | // 滑动容器的 translateY
63 | y: number
64 | // 滑动容器在 X 方向的最大滑动距离,正值
65 | maxScrollDistanceX: number
66 | // 滑动容器在 Y 方向的最大滑动距离,正值
67 | maxScrollDistanceY: number
68 | }): void
69 | }
70 |
71 | function onScroll(callback: ScrollCallback): () => void
72 | ```
73 |
74 | 示例
75 | ```js
76 | // 在页面中任意引入到的 *.wxs 文件
77 | var weappScroll = require('./weapp-scroll.wxs')
78 |
79 | var cancel = weappScroll.onScroll(function (data) {
80 | console.log(data.x)
81 | })
82 |
83 | // 取消监听
84 | cancel()
85 | ```
86 |
87 | ## License
88 |
89 | [MIT](https://github.com/haiya6/weapp-scroll/blob/main/LICENSE)
90 |
--------------------------------------------------------------------------------
/dist/index.wxs:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Easing = {
4 | v1: function (t) {
5 | return 1 + --t * t * t * t * t;
6 | },
7 | v2: function (t) {
8 | return t * (2 - t);
9 | },
10 | v3: function (t) {
11 | return 1 - --t * t * t * t;
12 | }
13 | };
14 |
15 | var Utils = {
16 | isUndefined: function (val) {
17 | return typeof val === 'undefined';
18 | },
19 | clamp: function (min, max, val) {
20 | return Math.max(min, Math.min(max, val));
21 | },
22 | clonePos: function (pos) {
23 | return {
24 | x: pos.x,
25 | y: pos.y
26 | };
27 | },
28 | isSamePos: function (p1, p2) {
29 | return p1.x === p2.x && p1.y === p2.y;
30 | }
31 | };
32 |
33 | var options = {
34 | enableScrollX: false,
35 | enableScrollY: false,
36 | slidingContainerSelector: '.content',
37 | damping: 0.3,
38 | deceleration: 0.0015,
39 | momentumDuration: 1800,
40 | momentumOutBoundsDuration: 400,
41 | bounceDuration: 800
42 | };
43 | function setOption(userOptions, key) {
44 | if (!Utils.isUndefined(userOptions[key])) {
45 | options[key] = userOptions[key];
46 | }
47 | }
48 | function resolveOptions(userOptions) {
49 | setOption(userOptions, 'slidingContainerSelector');
50 | setOption(userOptions, 'damping');
51 | setOption(userOptions, 'bounceDuration');
52 | }
53 |
54 | var ownerInstance;
55 | var containerRect;
56 | var slidingContainerInstance;
57 | var slidingContainerRect;
58 | var canScrollX = false;
59 | var canScrollY = false;
60 | var minTranslateX;
61 | var maxTranslateX = 0;
62 | var minTranslateY;
63 | var maxTranslateY = 0;
64 | var pos = { x: 0, y: 0 };
65 | var startTouch = { clientX: 0, clientY: 0 };
66 | var startPos = { x: 0, y: 0 };
67 | var startTimeStamp = 0;
68 | var effect = null;
69 | var onScrollCallbacks = [];
70 | function setTranslate(pos0) {
71 | if (Utils.isSamePos(pos0, pos))
72 | return;
73 | slidingContainerInstance.setStyle({
74 | transform: 'translateX(' + pos0.x + 'px) translateY(' + pos0.y + 'px)'
75 | });
76 | pos.x = pos0.x;
77 | pos.y = pos0.y;
78 | onScrollCallbacks.forEach(function (cb) { return cb({
79 | x: pos.x,
80 | y: pos.y,
81 | maxScrollDistanceX: minTranslateX * -1,
82 | maxScrollDistanceY: minTranslateY * -1
83 | }); });
84 | }
85 | function moveFromTo(fromPos, toPos, duration, timing, onComplete) {
86 | var aborted = false;
87 | var completed = false;
88 | fromPos = Utils.clonePos(fromPos);
89 | toPos = Utils.clonePos(toPos);
90 | if (duration === 0) {
91 | setTranslate(toPos);
92 | ownerInstance.requestAnimationFrame(function () {
93 | completed = true;
94 | onComplete && onComplete();
95 | });
96 | }
97 | else {
98 | var startTime = Date.now();
99 | var disX = toPos.x - fromPos.x;
100 | var disY = toPos.y - fromPos.y;
101 | var progressX = 1;
102 | var progressY = 1;
103 | var rAFHandler = function rAFHandler() {
104 | if (aborted)
105 | return;
106 | var curPos = Utils.clonePos(fromPos);
107 | if (canScrollX) {
108 | progressX = timing.x(Utils.clamp(0, 1, (Date.now() - startTime) / duration));
109 | curPos.x = disX * progressX + fromPos.x;
110 | }
111 | if (canScrollY) {
112 | progressY = timing.y(Utils.clamp(0, 1, (Date.now() - startTime) / duration));
113 | curPos.y = disY * progressY + fromPos.y;
114 | }
115 | setTranslate(curPos);
116 | if (progressX < 1 || progressY < 1) {
117 | ownerInstance.requestAnimationFrame(rAFHandler);
118 | }
119 | else {
120 | completed = true;
121 | onComplete && onComplete();
122 | }
123 | };
124 | ownerInstance.requestAnimationFrame(rAFHandler);
125 | }
126 | if (effect)
127 | effect();
128 | effect = function abort() {
129 | if (!completed && !aborted) {
130 | aborted = true;
131 | }
132 | };
133 | }
134 | function positionCorrection(pos) {
135 | var correctedPos = {
136 | x: Utils.clamp(minTranslateX, maxTranslateX, pos.x),
137 | y: Utils.clamp(minTranslateY, maxTranslateY, pos.y)
138 | };
139 | if (!Utils.isSamePos(correctedPos, pos)) {
140 | moveFromTo(pos, correctedPos, options.bounceDuration, { x: Easing.v3, y: Easing.v3 });
141 | }
142 | }
143 | function setup(_options, _, _ownerInstance, instance) {
144 | resolveOptions(_options);
145 | ownerInstance = _ownerInstance;
146 | containerRect = instance.getBoundingClientRect();
147 | slidingContainerInstance = ownerInstance.selectComponent(options.slidingContainerSelector);
148 | slidingContainerRect = slidingContainerInstance.getBoundingClientRect();
149 | if (slidingContainerRect.width > containerRect.width) {
150 | canScrollX = Utils.isUndefined(_options.enableScrollX) ? true : _options.enableScrollX;
151 | minTranslateX = (slidingContainerRect.width - containerRect.width) * -1;
152 | }
153 | if (slidingContainerRect.height > containerRect.height) {
154 | canScrollY = Utils.isUndefined(_options.enableScrollY) ? true : _options.enableScrollY;
155 | minTranslateY = (slidingContainerRect.height - containerRect.height) * -1;
156 | }
157 | }
158 | function touchstart(event) {
159 | startTouch.clientX = event.changedTouches[0].clientX;
160 | startTouch.clientY = event.changedTouches[0].clientY;
161 | startPos.x = pos.x;
162 | startPos.y = pos.y;
163 | startTimeStamp = event.timeStamp;
164 | if (effect) {
165 | effect();
166 | effect = null;
167 | }
168 | }
169 | function touchmove(event) {
170 | var deltaX = event.changedTouches[0].clientX - startTouch.clientX;
171 | var deltaY = event.changedTouches[0].clientY - startTouch.clientY;
172 | var x = startPos.x;
173 | var y = startPos.y;
174 | if (canScrollX) {
175 | x += deltaX;
176 | if (x > maxTranslateX) {
177 | x = maxTranslateX + options.damping * (x - maxTranslateX);
178 | }
179 | else if (x < minTranslateX) {
180 | x = minTranslateX + options.damping * (x - minTranslateX);
181 | }
182 | }
183 | if (canScrollY) {
184 | y += deltaY;
185 | if (y > maxTranslateY) {
186 | y = maxTranslateY + options.damping * (y - maxTranslateY);
187 | }
188 | else if (y < minTranslateY) {
189 | y = minTranslateY + options.damping * (y - minTranslateY);
190 | }
191 | }
192 | setTranslate({ x: x, y: y });
193 | }
194 | function touchend(event) {
195 | var minMovingDistance = 15;
196 | var maxMovingDuration = 300;
197 | var finalPos = { x: pos.x, y: pos.y };
198 | if (Utils.isSamePos(finalPos, startPos))
199 | return;
200 | var eventDuration = event.timeStamp - startTimeStamp;
201 | if (eventDuration > maxMovingDuration) {
202 | positionCorrection(finalPos);
203 | return;
204 | }
205 | var distanceX = Math.abs(finalPos.x - startPos.x);
206 | var distanceY = Math.abs(finalPos.y - startPos.y);
207 | var durationX = 0;
208 | var durationY = 0;
209 | var timingX = Easing.v1;
210 | var timingY = Easing.v1;
211 | var calculateMomentum = function calculateMomentum(start, end, distance) {
212 | var speed = distance / eventDuration;
213 | var dir = end - start > 0 ? 1 : -1;
214 | var duration = Math.min(options.momentumDuration, (speed * 2) / options.deceleration);
215 | var delta = Math.pow(speed, 2) / options.deceleration * dir;
216 | return {
217 | duration: duration,
218 | delta: delta
219 | };
220 | };
221 | if (canScrollX
222 | && distanceX > minMovingDistance
223 | && finalPos.x <= maxTranslateX
224 | && finalPos.x >= minTranslateX) {
225 | var result = calculateMomentum(startPos.x, pos.x, distanceX);
226 | durationX = result.duration;
227 | finalPos.x += result.delta;
228 | if (finalPos.x > maxTranslateX || finalPos.x < minTranslateX) {
229 | durationX = options.momentumOutBoundsDuration;
230 | timingX = Easing.v2;
231 | var beyondDis = containerRect.width / 6;
232 | if (finalPos.x > maxTranslateX) {
233 | finalPos.x = maxTranslateX + beyondDis;
234 | }
235 | else {
236 | finalPos.x = minTranslateX + beyondDis * -1;
237 | }
238 | }
239 | }
240 | if (canScrollY
241 | && distanceY > minMovingDistance
242 | && finalPos.y >= minTranslateY
243 | && finalPos.y <= maxTranslateY) {
244 | var result = calculateMomentum(startPos.y, pos.y, distanceY);
245 | durationY = result.duration;
246 | finalPos.y += result.delta;
247 | if (finalPos.y > maxTranslateY || finalPos.y < minTranslateY) {
248 | durationY = options.momentumOutBoundsDuration;
249 | timingY = Easing.v2;
250 | var beyondDis = containerRect.height / 6;
251 | if (finalPos.y > maxTranslateY) {
252 | finalPos.y = maxTranslateY + beyondDis;
253 | }
254 | else {
255 | finalPos.y = minTranslateY + beyondDis * -1;
256 | }
257 | }
258 | }
259 | moveFromTo(pos, finalPos, Math.max(durationX, durationY), { x: timingX, y: timingY }, function () {
260 | positionCorrection(finalPos);
261 | });
262 | }
263 | function onScroll(callback) {
264 | onScrollCallbacks.push(callback);
265 | return function cancel() {
266 | var idx = onScrollCallbacks.indexOf(callback);
267 | if (idx !== 1) {
268 | onScrollCallbacks.splice(idx, 1);
269 | }
270 | };
271 | }
272 |
273 | var index = {
274 | setup: setup,
275 | touchstart: touchstart,
276 | touchmove: touchmove,
277 | touchend: touchend,
278 | onScroll: onScroll
279 | };
280 |
281 | module.exports = index;
282 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | project.private.config.json
3 |
--------------------------------------------------------------------------------
/example/app.js:
--------------------------------------------------------------------------------
1 | App({})
2 |
--------------------------------------------------------------------------------
/example/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "pages/index/index",
4 | "pages/vertical/index",
5 | "pages/dynamic/index",
6 | "pages/multiple/index"
7 | ],
8 | "window": {
9 | "backgroundTextStyle": "light",
10 | "navigationBarBackgroundColor": "#fff",
11 | "navigationBarTitleText": "Weapp Scroll",
12 | "navigationBarTextStyle": "black"
13 | },
14 | "sitemapLocation": "sitemap.json"
15 | }
--------------------------------------------------------------------------------
/example/app.wxss:
--------------------------------------------------------------------------------
1 | page {
2 | padding: 0 32rpx;
3 | }
4 |
5 | page, view {
6 | box-sizing: border-box;
7 | }
8 |
9 | .label {
10 | font-size: 32rpx;
11 | line-height: 32rpx;
12 | color: #000;
13 | margin: 30rpx 0;
14 | }
15 |
16 | .container {
17 | width: 100%;
18 | height: 300rpx;
19 | overflow: hidden;
20 | }
21 |
22 | .container.vertical {
23 | height: 100vh;
24 | }
25 |
26 | .container .content {
27 | display: inline-block;
28 | white-space: nowrap;
29 | }
30 |
31 | .container.vertical .content {
32 | display: block;
33 | }
34 |
35 | .container .content .item {
36 | display: inline-flex;
37 | justify-content: center;
38 | align-items: center;
39 | width: 200rpx;
40 | height: 300rpx;
41 | border: 1px solid;
42 | }
43 |
44 | .container.vertical .content .item {
45 | width: 100%;
46 | display: flex;
47 | }
48 |
49 | .button {
50 | margin: 30rpx 0;
51 | }
--------------------------------------------------------------------------------
/example/pages/dynamic/index.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | count: 1,
4 | weappScrollOptions: {
5 | slidingContainerSelector: '.content'
6 | }
7 | },
8 | onLoad() {
9 | setTimeout(() => {
10 | this.setData({
11 | count: 10,
12 | // 结构改变后,需要重新触发 scroll.setup 来进行相关初始化
13 | // 这里目的就是使用 setData 重设置 weappScrollOptions,从而触发 change:_ 监听,重新执行 scroll.setup 方法
14 | // 可设置下面这行代码,或 'weappScrollOptions.t': Date.now()
15 | weappScrollOptions: this.data.weappScrollOptions
16 | })
17 | }, 0);
18 | }
19 | })
20 |
--------------------------------------------------------------------------------
/example/pages/dynamic/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | },
4 | "disableScroll": true
5 | }
--------------------------------------------------------------------------------
/example/pages/dynamic/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 动态添加元素后需要手动触发更新
4 |
13 |
14 | {{ item }}
15 |
16 |
17 |
--------------------------------------------------------------------------------
/example/pages/index/index.js:
--------------------------------------------------------------------------------
1 | Page({
2 | data: {
3 | weappsScrollOptions: {
4 | slidingContainerSelector: '.content',
5 | }
6 | },
7 | toVertical() {
8 | wx.navigateTo({
9 | url: '/pages/vertical/index'
10 | })
11 | },
12 | toDynamic() {
13 | wx.navigateTo({
14 | url: '/pages/dynamic/index'
15 | })
16 | },
17 | toMultiple() {
18 | wx.navigateTo({
19 | url: '/pages/multiple/index'
20 | })
21 | }
22 | })
23 |
--------------------------------------------------------------------------------
/example/pages/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true
3 | }
--------------------------------------------------------------------------------
/example/pages/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | var weappScroll = require('../../weapp-scroll.wxs')
5 |
6 | var cancel = weappScroll.onScroll(function(data) {
7 | console.log('x:', data.x, 'y:', data.y)
8 | })
9 |
10 | // 取消监听
11 | // cancel()
12 |
13 |
14 | 横向滚动
15 |
24 |
25 | {{ item }}
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/example/pages/multiple/comp1/index.js:
--------------------------------------------------------------------------------
1 | Page({})
2 |
--------------------------------------------------------------------------------
/example/pages/multiple/comp1/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/example/pages/multiple/comp1/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 | {{ item }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/example/pages/multiple/comp2/index.js:
--------------------------------------------------------------------------------
1 | Page({})
2 |
--------------------------------------------------------------------------------
/example/pages/multiple/comp2/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true
3 | }
--------------------------------------------------------------------------------
/example/pages/multiple/comp2/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 | {{ item }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/example/pages/multiple/index.js:
--------------------------------------------------------------------------------
1 | Page({})
2 |
--------------------------------------------------------------------------------
/example/pages/multiple/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "comp1": "./comp1/index",
4 | "comp2": "./comp2/index"
5 | },
6 | "disableScroll": true
7 | }
--------------------------------------------------------------------------------
/example/pages/multiple/index.wxml:
--------------------------------------------------------------------------------
1 | 页面中多个滚动容器需要用组件隔离
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/example/pages/vertical/index.js:
--------------------------------------------------------------------------------
1 | Page({
2 |
3 | })
--------------------------------------------------------------------------------
/example/pages/vertical/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "disableScroll": true
3 | }
--------------------------------------------------------------------------------
/example/pages/vertical/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 | {{ item }}
14 |
15 |
16 |
--------------------------------------------------------------------------------
/example/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "appid": "",
3 | "compileType": "miniprogram",
4 | "libVersion": "2.25.0",
5 | "packOptions": {
6 | "ignore": [],
7 | "include": []
8 | },
9 | "setting": {
10 | "urlCheck": true,
11 | "coverView": true,
12 | "es6": true,
13 | "postcss": true,
14 | "lazyloadPlaceholderEnable": false,
15 | "preloadBackgroundData": false,
16 | "minified": true,
17 | "autoAudits": false,
18 | "uglifyFileName": false,
19 | "uploadWithSourceMap": true,
20 | "enhance": true,
21 | "showShadowRootInWxmlPanel": true,
22 | "packNpmManually": false,
23 | "packNpmRelationList": [],
24 | "minifyWXSS": true,
25 | "useStaticServer": true,
26 | "showES6CompileOption": false,
27 | "checkInvalidKey": true,
28 | "babelSetting": {
29 | "ignore": [],
30 | "disablePlugins": [],
31 | "outputPath": ""
32 | },
33 | "disableUseStrict": false,
34 | "useCompilerPlugins": false,
35 | "minifyWXML": true
36 | },
37 | "condition": {},
38 | "editorSetting": {
39 | "tabIndent": "insertSpaces",
40 | "tabSize": 2
41 | },
42 | "description": "项目配置文件,详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html"
43 | }
--------------------------------------------------------------------------------
/example/sitemap.json:
--------------------------------------------------------------------------------
1 | {
2 | "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
3 | "rules": [{
4 | "action": "allow",
5 | "page": "*"
6 | }]
7 | }
--------------------------------------------------------------------------------
/example/weapp-scroll.wxs:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Easing = {
4 | v1: function (t) {
5 | return 1 + --t * t * t * t * t;
6 | },
7 | v2: function (t) {
8 | return t * (2 - t);
9 | },
10 | v3: function (t) {
11 | return 1 - --t * t * t * t;
12 | }
13 | };
14 |
15 | var Utils = {
16 | isUndefined: function (val) {
17 | return typeof val === 'undefined';
18 | },
19 | clamp: function (min, max, val) {
20 | return Math.max(min, Math.min(max, val));
21 | },
22 | clonePos: function (pos) {
23 | return {
24 | x: pos.x,
25 | y: pos.y
26 | };
27 | },
28 | isSamePos: function (p1, p2) {
29 | return p1.x === p2.x && p1.y === p2.y;
30 | }
31 | };
32 |
33 | var options = {
34 | enableScrollX: false,
35 | enableScrollY: false,
36 | slidingContainerSelector: '.content',
37 | damping: 0.3,
38 | deceleration: 0.0015,
39 | momentumDuration: 1800,
40 | momentumOutBoundsDuration: 400,
41 | bounceDuration: 800
42 | };
43 | function setOption(userOptions, key) {
44 | if (!Utils.isUndefined(userOptions[key])) {
45 | options[key] = userOptions[key];
46 | }
47 | }
48 | function resolveOptions(userOptions) {
49 | setOption(userOptions, 'slidingContainerSelector');
50 | setOption(userOptions, 'damping');
51 | setOption(userOptions, 'bounceDuration');
52 | }
53 |
54 | var ownerInstance;
55 | var containerRect;
56 | var slidingContainerInstance;
57 | var slidingContainerRect;
58 | var canScrollX = false;
59 | var canScrollY = false;
60 | var minTranslateX;
61 | var maxTranslateX = 0;
62 | var minTranslateY;
63 | var maxTranslateY = 0;
64 | var pos = { x: 0, y: 0 };
65 | var startTouch = { clientX: 0, clientY: 0 };
66 | var startPos = { x: 0, y: 0 };
67 | var startTimeStamp = 0;
68 | var effect = null;
69 | var onScrollCallbacks = [];
70 | function setTranslate(pos0) {
71 | if (Utils.isSamePos(pos0, pos))
72 | return;
73 | slidingContainerInstance.setStyle({
74 | transform: 'translateX(' + pos0.x + 'px) translateY(' + pos0.y + 'px)'
75 | });
76 | pos.x = pos0.x;
77 | pos.y = pos0.y;
78 | onScrollCallbacks.forEach(function (cb) { return cb({
79 | x: pos.x,
80 | y: pos.y,
81 | maxScrollDistanceX: minTranslateX * -1,
82 | maxScrollDistanceY: minTranslateY * -1
83 | }); });
84 | }
85 | function moveFromTo(fromPos, toPos, duration, timing, onComplete) {
86 | var aborted = false;
87 | var completed = false;
88 | fromPos = Utils.clonePos(fromPos);
89 | toPos = Utils.clonePos(toPos);
90 | if (duration === 0) {
91 | setTranslate(toPos);
92 | ownerInstance.requestAnimationFrame(function () {
93 | completed = true;
94 | onComplete && onComplete();
95 | });
96 | }
97 | else {
98 | var startTime = Date.now();
99 | var disX = toPos.x - fromPos.x;
100 | var disY = toPos.y - fromPos.y;
101 | var progressX = 1;
102 | var progressY = 1;
103 | var rAFHandler = function rAFHandler() {
104 | if (aborted)
105 | return;
106 | var curPos = Utils.clonePos(fromPos);
107 | if (canScrollX) {
108 | progressX = timing.x(Utils.clamp(0, 1, (Date.now() - startTime) / duration));
109 | curPos.x = disX * progressX + fromPos.x;
110 | }
111 | if (canScrollY) {
112 | progressY = timing.y(Utils.clamp(0, 1, (Date.now() - startTime) / duration));
113 | curPos.y = disY * progressY + fromPos.y;
114 | }
115 | setTranslate(curPos);
116 | if (progressX < 1 || progressY < 1) {
117 | ownerInstance.requestAnimationFrame(rAFHandler);
118 | }
119 | else {
120 | completed = true;
121 | onComplete && onComplete();
122 | }
123 | };
124 | ownerInstance.requestAnimationFrame(rAFHandler);
125 | }
126 | if (effect)
127 | effect();
128 | effect = function abort() {
129 | if (!completed && !aborted) {
130 | aborted = true;
131 | }
132 | };
133 | }
134 | function positionCorrection(pos) {
135 | var correctedPos = {
136 | x: Utils.clamp(minTranslateX, maxTranslateX, pos.x),
137 | y: Utils.clamp(minTranslateY, maxTranslateY, pos.y)
138 | };
139 | if (!Utils.isSamePos(correctedPos, pos)) {
140 | moveFromTo(pos, correctedPos, options.bounceDuration, { x: Easing.v3, y: Easing.v3 });
141 | }
142 | }
143 | function setup(_options, _, _ownerInstance, instance) {
144 | resolveOptions(_options);
145 | ownerInstance = _ownerInstance;
146 | containerRect = instance.getBoundingClientRect();
147 | slidingContainerInstance = ownerInstance.selectComponent(options.slidingContainerSelector);
148 | slidingContainerRect = slidingContainerInstance.getBoundingClientRect();
149 | if (slidingContainerRect.width > containerRect.width) {
150 | canScrollX = Utils.isUndefined(_options.enableScrollX) ? true : _options.enableScrollX;
151 | minTranslateX = (slidingContainerRect.width - containerRect.width) * -1;
152 | }
153 | if (slidingContainerRect.height > containerRect.height) {
154 | canScrollY = Utils.isUndefined(_options.enableScrollY) ? true : _options.enableScrollY;
155 | minTranslateY = (slidingContainerRect.height - containerRect.height) * -1;
156 | }
157 | }
158 | function touchstart(event) {
159 | startTouch.clientX = event.changedTouches[0].clientX;
160 | startTouch.clientY = event.changedTouches[0].clientY;
161 | startPos.x = pos.x;
162 | startPos.y = pos.y;
163 | startTimeStamp = event.timeStamp;
164 | if (effect) {
165 | effect();
166 | effect = null;
167 | }
168 | }
169 | function touchmove(event) {
170 | var deltaX = event.changedTouches[0].clientX - startTouch.clientX;
171 | var deltaY = event.changedTouches[0].clientY - startTouch.clientY;
172 | var x = startPos.x;
173 | var y = startPos.y;
174 | if (canScrollX) {
175 | x += deltaX;
176 | if (x > maxTranslateX) {
177 | x = maxTranslateX + options.damping * (x - maxTranslateX);
178 | }
179 | else if (x < minTranslateX) {
180 | x = minTranslateX + options.damping * (x - minTranslateX);
181 | }
182 | }
183 | if (canScrollY) {
184 | y += deltaY;
185 | if (y > maxTranslateY) {
186 | y = maxTranslateY + options.damping * (y - maxTranslateY);
187 | }
188 | else if (y < minTranslateY) {
189 | y = minTranslateY + options.damping * (y - minTranslateY);
190 | }
191 | }
192 | setTranslate({ x: x, y: y });
193 | }
194 | function touchend(event) {
195 | var minMovingDistance = 15;
196 | var maxMovingDuration = 300;
197 | var finalPos = { x: pos.x, y: pos.y };
198 | if (Utils.isSamePos(finalPos, startPos))
199 | return;
200 | var eventDuration = event.timeStamp - startTimeStamp;
201 | if (eventDuration > maxMovingDuration) {
202 | positionCorrection(finalPos);
203 | return;
204 | }
205 | var distanceX = Math.abs(finalPos.x - startPos.x);
206 | var distanceY = Math.abs(finalPos.y - startPos.y);
207 | var durationX = 0;
208 | var durationY = 0;
209 | var timingX = Easing.v1;
210 | var timingY = Easing.v1;
211 | var calculateMomentum = function calculateMomentum(start, end, distance) {
212 | var speed = distance / eventDuration;
213 | var dir = end - start > 0 ? 1 : -1;
214 | var duration = Math.min(options.momentumDuration, (speed * 2) / options.deceleration);
215 | var delta = Math.pow(speed, 2) / options.deceleration * dir;
216 | return {
217 | duration: duration,
218 | delta: delta
219 | };
220 | };
221 | if (canScrollX
222 | && distanceX > minMovingDistance
223 | && finalPos.x <= maxTranslateX
224 | && finalPos.x >= minTranslateX) {
225 | var result = calculateMomentum(startPos.x, pos.x, distanceX);
226 | durationX = result.duration;
227 | finalPos.x += result.delta;
228 | if (finalPos.x > maxTranslateX || finalPos.x < minTranslateX) {
229 | durationX = options.momentumOutBoundsDuration;
230 | timingX = Easing.v2;
231 | var beyondDis = containerRect.width / 6;
232 | if (finalPos.x > maxTranslateX) {
233 | finalPos.x = maxTranslateX + beyondDis;
234 | }
235 | else {
236 | finalPos.x = minTranslateX + beyondDis * -1;
237 | }
238 | }
239 | }
240 | if (canScrollY
241 | && distanceY > minMovingDistance
242 | && finalPos.y >= minTranslateY
243 | && finalPos.y <= maxTranslateY) {
244 | var result = calculateMomentum(startPos.y, pos.y, distanceY);
245 | durationY = result.duration;
246 | finalPos.y += result.delta;
247 | if (finalPos.y > maxTranslateY || finalPos.y < minTranslateY) {
248 | durationY = options.momentumOutBoundsDuration;
249 | timingY = Easing.v2;
250 | var beyondDis = containerRect.height / 6;
251 | if (finalPos.y > maxTranslateY) {
252 | finalPos.y = maxTranslateY + beyondDis;
253 | }
254 | else {
255 | finalPos.y = minTranslateY + beyondDis * -1;
256 | }
257 | }
258 | }
259 | moveFromTo(pos, finalPos, Math.max(durationX, durationY), { x: timingX, y: timingY }, function () {
260 | positionCorrection(finalPos);
261 | });
262 | }
263 | function onScroll(callback) {
264 | onScrollCallbacks.push(callback);
265 | return function cancel() {
266 | var idx = onScrollCallbacks.indexOf(callback);
267 | if (idx !== 1) {
268 | onScrollCallbacks.splice(idx, 1);
269 | }
270 | };
271 | }
272 |
273 | var index = {
274 | setup: setup,
275 | touchstart: touchstart,
276 | touchmove: touchmove,
277 | touchend: touchend,
278 | onScroll: onScroll
279 | };
280 |
281 | module.exports = index;
282 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "weapp-scroll",
3 | "version": "1.0.4",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "weapp-scroll",
9 | "version": "1.0.4",
10 | "license": "MIT",
11 | "devDependencies": {
12 | "@rollup/plugin-typescript": "^8.3.3",
13 | "miniprogram-api-typings": "^3.5.0",
14 | "rollup": "^2.76.0",
15 | "rollup-plugin-copy": "^3.4.0",
16 | "tslib": "^2.4.0",
17 | "typescript": "^4.7.4"
18 | }
19 | },
20 | "node_modules/@nodelib/fs.scandir": {
21 | "version": "2.1.5",
22 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
23 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
24 | "dev": true,
25 | "dependencies": {
26 | "@nodelib/fs.stat": "2.0.5",
27 | "run-parallel": "^1.1.9"
28 | },
29 | "engines": {
30 | "node": ">= 8"
31 | }
32 | },
33 | "node_modules/@nodelib/fs.stat": {
34 | "version": "2.0.5",
35 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
36 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
37 | "dev": true,
38 | "engines": {
39 | "node": ">= 8"
40 | }
41 | },
42 | "node_modules/@nodelib/fs.walk": {
43 | "version": "1.2.8",
44 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
45 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
46 | "dev": true,
47 | "dependencies": {
48 | "@nodelib/fs.scandir": "2.1.5",
49 | "fastq": "^1.6.0"
50 | },
51 | "engines": {
52 | "node": ">= 8"
53 | }
54 | },
55 | "node_modules/@rollup/plugin-typescript": {
56 | "version": "8.3.3",
57 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.3.tgz",
58 | "integrity": "sha512-55L9SyiYu3r/JtqdjhwcwaECXP7JeJ9h1Sg1VWRJKIutla2MdZQodTgcCNybXLMCnqpNLEhS2vGENww98L1npg==",
59 | "dev": true,
60 | "dependencies": {
61 | "@rollup/pluginutils": "^3.1.0",
62 | "resolve": "^1.17.0"
63 | },
64 | "engines": {
65 | "node": ">=8.0.0"
66 | },
67 | "peerDependencies": {
68 | "rollup": "^2.14.0",
69 | "tslib": "*",
70 | "typescript": ">=3.7.0"
71 | },
72 | "peerDependenciesMeta": {
73 | "tslib": {
74 | "optional": true
75 | }
76 | }
77 | },
78 | "node_modules/@rollup/pluginutils": {
79 | "version": "3.1.0",
80 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
81 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
82 | "dev": true,
83 | "dependencies": {
84 | "@types/estree": "0.0.39",
85 | "estree-walker": "^1.0.1",
86 | "picomatch": "^2.2.2"
87 | },
88 | "engines": {
89 | "node": ">= 8.0.0"
90 | },
91 | "peerDependencies": {
92 | "rollup": "^1.20.0||^2.0.0"
93 | }
94 | },
95 | "node_modules/@types/estree": {
96 | "version": "0.0.39",
97 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
98 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
99 | "dev": true
100 | },
101 | "node_modules/@types/fs-extra": {
102 | "version": "8.1.2",
103 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz",
104 | "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==",
105 | "dev": true,
106 | "dependencies": {
107 | "@types/node": "*"
108 | }
109 | },
110 | "node_modules/@types/glob": {
111 | "version": "7.2.0",
112 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
113 | "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
114 | "dev": true,
115 | "dependencies": {
116 | "@types/minimatch": "*",
117 | "@types/node": "*"
118 | }
119 | },
120 | "node_modules/@types/minimatch": {
121 | "version": "3.0.5",
122 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
123 | "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
124 | "dev": true
125 | },
126 | "node_modules/@types/node": {
127 | "version": "18.0.3",
128 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
129 | "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==",
130 | "dev": true
131 | },
132 | "node_modules/array-union": {
133 | "version": "2.1.0",
134 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
135 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
136 | "dev": true,
137 | "engines": {
138 | "node": ">=8"
139 | }
140 | },
141 | "node_modules/balanced-match": {
142 | "version": "1.0.2",
143 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
144 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
145 | "dev": true
146 | },
147 | "node_modules/brace-expansion": {
148 | "version": "1.1.11",
149 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
150 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
151 | "dev": true,
152 | "dependencies": {
153 | "balanced-match": "^1.0.0",
154 | "concat-map": "0.0.1"
155 | }
156 | },
157 | "node_modules/braces": {
158 | "version": "3.0.2",
159 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
160 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
161 | "dev": true,
162 | "dependencies": {
163 | "fill-range": "^7.0.1"
164 | },
165 | "engines": {
166 | "node": ">=8"
167 | }
168 | },
169 | "node_modules/colorette": {
170 | "version": "1.4.0",
171 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
172 | "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
173 | "dev": true
174 | },
175 | "node_modules/concat-map": {
176 | "version": "0.0.1",
177 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
178 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
179 | "dev": true
180 | },
181 | "node_modules/dir-glob": {
182 | "version": "3.0.1",
183 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
184 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
185 | "dev": true,
186 | "dependencies": {
187 | "path-type": "^4.0.0"
188 | },
189 | "engines": {
190 | "node": ">=8"
191 | }
192 | },
193 | "node_modules/estree-walker": {
194 | "version": "1.0.1",
195 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
196 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
197 | "dev": true
198 | },
199 | "node_modules/fast-glob": {
200 | "version": "3.2.11",
201 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
202 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
203 | "dev": true,
204 | "dependencies": {
205 | "@nodelib/fs.stat": "^2.0.2",
206 | "@nodelib/fs.walk": "^1.2.3",
207 | "glob-parent": "^5.1.2",
208 | "merge2": "^1.3.0",
209 | "micromatch": "^4.0.4"
210 | },
211 | "engines": {
212 | "node": ">=8.6.0"
213 | }
214 | },
215 | "node_modules/fastq": {
216 | "version": "1.13.0",
217 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
218 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
219 | "dev": true,
220 | "dependencies": {
221 | "reusify": "^1.0.4"
222 | }
223 | },
224 | "node_modules/fill-range": {
225 | "version": "7.0.1",
226 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
227 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
228 | "dev": true,
229 | "dependencies": {
230 | "to-regex-range": "^5.0.1"
231 | },
232 | "engines": {
233 | "node": ">=8"
234 | }
235 | },
236 | "node_modules/fs-extra": {
237 | "version": "8.1.0",
238 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
239 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
240 | "dev": true,
241 | "dependencies": {
242 | "graceful-fs": "^4.2.0",
243 | "jsonfile": "^4.0.0",
244 | "universalify": "^0.1.0"
245 | },
246 | "engines": {
247 | "node": ">=6 <7 || >=8"
248 | }
249 | },
250 | "node_modules/fs.realpath": {
251 | "version": "1.0.0",
252 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
253 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
254 | "dev": true
255 | },
256 | "node_modules/fsevents": {
257 | "version": "2.3.2",
258 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
259 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
260 | "dev": true,
261 | "hasInstallScript": true,
262 | "optional": true,
263 | "os": [
264 | "darwin"
265 | ],
266 | "engines": {
267 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
268 | }
269 | },
270 | "node_modules/function-bind": {
271 | "version": "1.1.1",
272 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
273 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
274 | "dev": true
275 | },
276 | "node_modules/glob": {
277 | "version": "7.2.3",
278 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
279 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
280 | "dev": true,
281 | "dependencies": {
282 | "fs.realpath": "^1.0.0",
283 | "inflight": "^1.0.4",
284 | "inherits": "2",
285 | "minimatch": "^3.1.1",
286 | "once": "^1.3.0",
287 | "path-is-absolute": "^1.0.0"
288 | },
289 | "engines": {
290 | "node": "*"
291 | },
292 | "funding": {
293 | "url": "https://github.com/sponsors/isaacs"
294 | }
295 | },
296 | "node_modules/glob-parent": {
297 | "version": "5.1.2",
298 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
299 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
300 | "dev": true,
301 | "dependencies": {
302 | "is-glob": "^4.0.1"
303 | },
304 | "engines": {
305 | "node": ">= 6"
306 | }
307 | },
308 | "node_modules/globby": {
309 | "version": "10.0.1",
310 | "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
311 | "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
312 | "dev": true,
313 | "dependencies": {
314 | "@types/glob": "^7.1.1",
315 | "array-union": "^2.1.0",
316 | "dir-glob": "^3.0.1",
317 | "fast-glob": "^3.0.3",
318 | "glob": "^7.1.3",
319 | "ignore": "^5.1.1",
320 | "merge2": "^1.2.3",
321 | "slash": "^3.0.0"
322 | },
323 | "engines": {
324 | "node": ">=8"
325 | }
326 | },
327 | "node_modules/graceful-fs": {
328 | "version": "4.2.10",
329 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
330 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
331 | "dev": true
332 | },
333 | "node_modules/has": {
334 | "version": "1.0.3",
335 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
336 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
337 | "dev": true,
338 | "dependencies": {
339 | "function-bind": "^1.1.1"
340 | },
341 | "engines": {
342 | "node": ">= 0.4.0"
343 | }
344 | },
345 | "node_modules/ignore": {
346 | "version": "5.2.0",
347 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
348 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
349 | "dev": true,
350 | "engines": {
351 | "node": ">= 4"
352 | }
353 | },
354 | "node_modules/inflight": {
355 | "version": "1.0.6",
356 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
357 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
358 | "dev": true,
359 | "dependencies": {
360 | "once": "^1.3.0",
361 | "wrappy": "1"
362 | }
363 | },
364 | "node_modules/inherits": {
365 | "version": "2.0.4",
366 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
367 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
368 | "dev": true
369 | },
370 | "node_modules/is-core-module": {
371 | "version": "2.9.0",
372 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
373 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
374 | "dev": true,
375 | "dependencies": {
376 | "has": "^1.0.3"
377 | },
378 | "funding": {
379 | "url": "https://github.com/sponsors/ljharb"
380 | }
381 | },
382 | "node_modules/is-extglob": {
383 | "version": "2.1.1",
384 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
385 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
386 | "dev": true,
387 | "engines": {
388 | "node": ">=0.10.0"
389 | }
390 | },
391 | "node_modules/is-glob": {
392 | "version": "4.0.3",
393 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
394 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
395 | "dev": true,
396 | "dependencies": {
397 | "is-extglob": "^2.1.1"
398 | },
399 | "engines": {
400 | "node": ">=0.10.0"
401 | }
402 | },
403 | "node_modules/is-number": {
404 | "version": "7.0.0",
405 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
406 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
407 | "dev": true,
408 | "engines": {
409 | "node": ">=0.12.0"
410 | }
411 | },
412 | "node_modules/is-plain-object": {
413 | "version": "3.0.1",
414 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
415 | "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
416 | "dev": true,
417 | "engines": {
418 | "node": ">=0.10.0"
419 | }
420 | },
421 | "node_modules/jsonfile": {
422 | "version": "4.0.0",
423 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
424 | "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
425 | "dev": true,
426 | "optionalDependencies": {
427 | "graceful-fs": "^4.1.6"
428 | }
429 | },
430 | "node_modules/merge2": {
431 | "version": "1.4.1",
432 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
433 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
434 | "dev": true,
435 | "engines": {
436 | "node": ">= 8"
437 | }
438 | },
439 | "node_modules/micromatch": {
440 | "version": "4.0.5",
441 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
442 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
443 | "dev": true,
444 | "dependencies": {
445 | "braces": "^3.0.2",
446 | "picomatch": "^2.3.1"
447 | },
448 | "engines": {
449 | "node": ">=8.6"
450 | }
451 | },
452 | "node_modules/minimatch": {
453 | "version": "3.1.2",
454 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
455 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
456 | "dev": true,
457 | "dependencies": {
458 | "brace-expansion": "^1.1.7"
459 | },
460 | "engines": {
461 | "node": "*"
462 | }
463 | },
464 | "node_modules/miniprogram-api-typings": {
465 | "version": "3.5.0",
466 | "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-3.5.0.tgz",
467 | "integrity": "sha512-cS/uXJTMGKujwoaeEFFFKqpCf7qp3R7iuQZWagZAwhKA3Z7U/xlhOcI3i1wqN+uo4YODg3AG1j2zCe1PDa9Wtg==",
468 | "dev": true
469 | },
470 | "node_modules/once": {
471 | "version": "1.4.0",
472 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
473 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
474 | "dev": true,
475 | "dependencies": {
476 | "wrappy": "1"
477 | }
478 | },
479 | "node_modules/path-is-absolute": {
480 | "version": "1.0.1",
481 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
482 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
483 | "dev": true,
484 | "engines": {
485 | "node": ">=0.10.0"
486 | }
487 | },
488 | "node_modules/path-parse": {
489 | "version": "1.0.7",
490 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
491 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
492 | "dev": true
493 | },
494 | "node_modules/path-type": {
495 | "version": "4.0.0",
496 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
497 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
498 | "dev": true,
499 | "engines": {
500 | "node": ">=8"
501 | }
502 | },
503 | "node_modules/picomatch": {
504 | "version": "2.3.1",
505 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
506 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
507 | "dev": true,
508 | "engines": {
509 | "node": ">=8.6"
510 | },
511 | "funding": {
512 | "url": "https://github.com/sponsors/jonschlinkert"
513 | }
514 | },
515 | "node_modules/queue-microtask": {
516 | "version": "1.2.3",
517 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
518 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
519 | "dev": true,
520 | "funding": [
521 | {
522 | "type": "github",
523 | "url": "https://github.com/sponsors/feross"
524 | },
525 | {
526 | "type": "patreon",
527 | "url": "https://www.patreon.com/feross"
528 | },
529 | {
530 | "type": "consulting",
531 | "url": "https://feross.org/support"
532 | }
533 | ]
534 | },
535 | "node_modules/resolve": {
536 | "version": "1.22.1",
537 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
538 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
539 | "dev": true,
540 | "dependencies": {
541 | "is-core-module": "^2.9.0",
542 | "path-parse": "^1.0.7",
543 | "supports-preserve-symlinks-flag": "^1.0.0"
544 | },
545 | "bin": {
546 | "resolve": "bin/resolve"
547 | },
548 | "funding": {
549 | "url": "https://github.com/sponsors/ljharb"
550 | }
551 | },
552 | "node_modules/reusify": {
553 | "version": "1.0.4",
554 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
555 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
556 | "dev": true,
557 | "engines": {
558 | "iojs": ">=1.0.0",
559 | "node": ">=0.10.0"
560 | }
561 | },
562 | "node_modules/rollup": {
563 | "version": "2.76.0",
564 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz",
565 | "integrity": "sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==",
566 | "dev": true,
567 | "bin": {
568 | "rollup": "dist/bin/rollup"
569 | },
570 | "engines": {
571 | "node": ">=10.0.0"
572 | },
573 | "optionalDependencies": {
574 | "fsevents": "~2.3.2"
575 | }
576 | },
577 | "node_modules/rollup-plugin-copy": {
578 | "version": "3.4.0",
579 | "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
580 | "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==",
581 | "dev": true,
582 | "dependencies": {
583 | "@types/fs-extra": "^8.0.1",
584 | "colorette": "^1.1.0",
585 | "fs-extra": "^8.1.0",
586 | "globby": "10.0.1",
587 | "is-plain-object": "^3.0.0"
588 | },
589 | "engines": {
590 | "node": ">=8.3"
591 | }
592 | },
593 | "node_modules/run-parallel": {
594 | "version": "1.2.0",
595 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
596 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
597 | "dev": true,
598 | "funding": [
599 | {
600 | "type": "github",
601 | "url": "https://github.com/sponsors/feross"
602 | },
603 | {
604 | "type": "patreon",
605 | "url": "https://www.patreon.com/feross"
606 | },
607 | {
608 | "type": "consulting",
609 | "url": "https://feross.org/support"
610 | }
611 | ],
612 | "dependencies": {
613 | "queue-microtask": "^1.2.2"
614 | }
615 | },
616 | "node_modules/slash": {
617 | "version": "3.0.0",
618 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
619 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
620 | "dev": true,
621 | "engines": {
622 | "node": ">=8"
623 | }
624 | },
625 | "node_modules/supports-preserve-symlinks-flag": {
626 | "version": "1.0.0",
627 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
628 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
629 | "dev": true,
630 | "engines": {
631 | "node": ">= 0.4"
632 | },
633 | "funding": {
634 | "url": "https://github.com/sponsors/ljharb"
635 | }
636 | },
637 | "node_modules/to-regex-range": {
638 | "version": "5.0.1",
639 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
640 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
641 | "dev": true,
642 | "dependencies": {
643 | "is-number": "^7.0.0"
644 | },
645 | "engines": {
646 | "node": ">=8.0"
647 | }
648 | },
649 | "node_modules/tslib": {
650 | "version": "2.4.0",
651 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
652 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
653 | "dev": true
654 | },
655 | "node_modules/typescript": {
656 | "version": "4.7.4",
657 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
658 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
659 | "dev": true,
660 | "bin": {
661 | "tsc": "bin/tsc",
662 | "tsserver": "bin/tsserver"
663 | },
664 | "engines": {
665 | "node": ">=4.2.0"
666 | }
667 | },
668 | "node_modules/universalify": {
669 | "version": "0.1.2",
670 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
671 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
672 | "dev": true,
673 | "engines": {
674 | "node": ">= 4.0.0"
675 | }
676 | },
677 | "node_modules/wrappy": {
678 | "version": "1.0.2",
679 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
680 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
681 | "dev": true
682 | }
683 | },
684 | "dependencies": {
685 | "@nodelib/fs.scandir": {
686 | "version": "2.1.5",
687 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
688 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
689 | "dev": true,
690 | "requires": {
691 | "@nodelib/fs.stat": "2.0.5",
692 | "run-parallel": "^1.1.9"
693 | }
694 | },
695 | "@nodelib/fs.stat": {
696 | "version": "2.0.5",
697 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
698 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
699 | "dev": true
700 | },
701 | "@nodelib/fs.walk": {
702 | "version": "1.2.8",
703 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
704 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
705 | "dev": true,
706 | "requires": {
707 | "@nodelib/fs.scandir": "2.1.5",
708 | "fastq": "^1.6.0"
709 | }
710 | },
711 | "@rollup/plugin-typescript": {
712 | "version": "8.3.3",
713 | "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.3.tgz",
714 | "integrity": "sha512-55L9SyiYu3r/JtqdjhwcwaECXP7JeJ9h1Sg1VWRJKIutla2MdZQodTgcCNybXLMCnqpNLEhS2vGENww98L1npg==",
715 | "dev": true,
716 | "requires": {
717 | "@rollup/pluginutils": "^3.1.0",
718 | "resolve": "^1.17.0"
719 | }
720 | },
721 | "@rollup/pluginutils": {
722 | "version": "3.1.0",
723 | "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
724 | "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
725 | "dev": true,
726 | "requires": {
727 | "@types/estree": "0.0.39",
728 | "estree-walker": "^1.0.1",
729 | "picomatch": "^2.2.2"
730 | }
731 | },
732 | "@types/estree": {
733 | "version": "0.0.39",
734 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
735 | "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
736 | "dev": true
737 | },
738 | "@types/fs-extra": {
739 | "version": "8.1.2",
740 | "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-8.1.2.tgz",
741 | "integrity": "sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg==",
742 | "dev": true,
743 | "requires": {
744 | "@types/node": "*"
745 | }
746 | },
747 | "@types/glob": {
748 | "version": "7.2.0",
749 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
750 | "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
751 | "dev": true,
752 | "requires": {
753 | "@types/minimatch": "*",
754 | "@types/node": "*"
755 | }
756 | },
757 | "@types/minimatch": {
758 | "version": "3.0.5",
759 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
760 | "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
761 | "dev": true
762 | },
763 | "@types/node": {
764 | "version": "18.0.3",
765 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz",
766 | "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==",
767 | "dev": true
768 | },
769 | "array-union": {
770 | "version": "2.1.0",
771 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
772 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
773 | "dev": true
774 | },
775 | "balanced-match": {
776 | "version": "1.0.2",
777 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
778 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
779 | "dev": true
780 | },
781 | "brace-expansion": {
782 | "version": "1.1.11",
783 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
784 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
785 | "dev": true,
786 | "requires": {
787 | "balanced-match": "^1.0.0",
788 | "concat-map": "0.0.1"
789 | }
790 | },
791 | "braces": {
792 | "version": "3.0.2",
793 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
794 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
795 | "dev": true,
796 | "requires": {
797 | "fill-range": "^7.0.1"
798 | }
799 | },
800 | "colorette": {
801 | "version": "1.4.0",
802 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
803 | "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
804 | "dev": true
805 | },
806 | "concat-map": {
807 | "version": "0.0.1",
808 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
809 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
810 | "dev": true
811 | },
812 | "dir-glob": {
813 | "version": "3.0.1",
814 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
815 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
816 | "dev": true,
817 | "requires": {
818 | "path-type": "^4.0.0"
819 | }
820 | },
821 | "estree-walker": {
822 | "version": "1.0.1",
823 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
824 | "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
825 | "dev": true
826 | },
827 | "fast-glob": {
828 | "version": "3.2.11",
829 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
830 | "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
831 | "dev": true,
832 | "requires": {
833 | "@nodelib/fs.stat": "^2.0.2",
834 | "@nodelib/fs.walk": "^1.2.3",
835 | "glob-parent": "^5.1.2",
836 | "merge2": "^1.3.0",
837 | "micromatch": "^4.0.4"
838 | }
839 | },
840 | "fastq": {
841 | "version": "1.13.0",
842 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
843 | "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
844 | "dev": true,
845 | "requires": {
846 | "reusify": "^1.0.4"
847 | }
848 | },
849 | "fill-range": {
850 | "version": "7.0.1",
851 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
852 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
853 | "dev": true,
854 | "requires": {
855 | "to-regex-range": "^5.0.1"
856 | }
857 | },
858 | "fs-extra": {
859 | "version": "8.1.0",
860 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
861 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
862 | "dev": true,
863 | "requires": {
864 | "graceful-fs": "^4.2.0",
865 | "jsonfile": "^4.0.0",
866 | "universalify": "^0.1.0"
867 | }
868 | },
869 | "fs.realpath": {
870 | "version": "1.0.0",
871 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
872 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
873 | "dev": true
874 | },
875 | "fsevents": {
876 | "version": "2.3.2",
877 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
878 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
879 | "dev": true,
880 | "optional": true
881 | },
882 | "function-bind": {
883 | "version": "1.1.1",
884 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
885 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
886 | "dev": true
887 | },
888 | "glob": {
889 | "version": "7.2.3",
890 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
891 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
892 | "dev": true,
893 | "requires": {
894 | "fs.realpath": "^1.0.0",
895 | "inflight": "^1.0.4",
896 | "inherits": "2",
897 | "minimatch": "^3.1.1",
898 | "once": "^1.3.0",
899 | "path-is-absolute": "^1.0.0"
900 | }
901 | },
902 | "glob-parent": {
903 | "version": "5.1.2",
904 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
905 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
906 | "dev": true,
907 | "requires": {
908 | "is-glob": "^4.0.1"
909 | }
910 | },
911 | "globby": {
912 | "version": "10.0.1",
913 | "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz",
914 | "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==",
915 | "dev": true,
916 | "requires": {
917 | "@types/glob": "^7.1.1",
918 | "array-union": "^2.1.0",
919 | "dir-glob": "^3.0.1",
920 | "fast-glob": "^3.0.3",
921 | "glob": "^7.1.3",
922 | "ignore": "^5.1.1",
923 | "merge2": "^1.2.3",
924 | "slash": "^3.0.0"
925 | }
926 | },
927 | "graceful-fs": {
928 | "version": "4.2.10",
929 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
930 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
931 | "dev": true
932 | },
933 | "has": {
934 | "version": "1.0.3",
935 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
936 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
937 | "dev": true,
938 | "requires": {
939 | "function-bind": "^1.1.1"
940 | }
941 | },
942 | "ignore": {
943 | "version": "5.2.0",
944 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
945 | "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
946 | "dev": true
947 | },
948 | "inflight": {
949 | "version": "1.0.6",
950 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
951 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
952 | "dev": true,
953 | "requires": {
954 | "once": "^1.3.0",
955 | "wrappy": "1"
956 | }
957 | },
958 | "inherits": {
959 | "version": "2.0.4",
960 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
961 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
962 | "dev": true
963 | },
964 | "is-core-module": {
965 | "version": "2.9.0",
966 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz",
967 | "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==",
968 | "dev": true,
969 | "requires": {
970 | "has": "^1.0.3"
971 | }
972 | },
973 | "is-extglob": {
974 | "version": "2.1.1",
975 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
976 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
977 | "dev": true
978 | },
979 | "is-glob": {
980 | "version": "4.0.3",
981 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
982 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
983 | "dev": true,
984 | "requires": {
985 | "is-extglob": "^2.1.1"
986 | }
987 | },
988 | "is-number": {
989 | "version": "7.0.0",
990 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
991 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
992 | "dev": true
993 | },
994 | "is-plain-object": {
995 | "version": "3.0.1",
996 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz",
997 | "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==",
998 | "dev": true
999 | },
1000 | "jsonfile": {
1001 | "version": "4.0.0",
1002 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
1003 | "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
1004 | "dev": true,
1005 | "requires": {
1006 | "graceful-fs": "^4.1.6"
1007 | }
1008 | },
1009 | "merge2": {
1010 | "version": "1.4.1",
1011 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
1012 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
1013 | "dev": true
1014 | },
1015 | "micromatch": {
1016 | "version": "4.0.5",
1017 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
1018 | "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
1019 | "dev": true,
1020 | "requires": {
1021 | "braces": "^3.0.2",
1022 | "picomatch": "^2.3.1"
1023 | }
1024 | },
1025 | "minimatch": {
1026 | "version": "3.1.2",
1027 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1028 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1029 | "dev": true,
1030 | "requires": {
1031 | "brace-expansion": "^1.1.7"
1032 | }
1033 | },
1034 | "miniprogram-api-typings": {
1035 | "version": "3.5.0",
1036 | "resolved": "https://registry.npmjs.org/miniprogram-api-typings/-/miniprogram-api-typings-3.5.0.tgz",
1037 | "integrity": "sha512-cS/uXJTMGKujwoaeEFFFKqpCf7qp3R7iuQZWagZAwhKA3Z7U/xlhOcI3i1wqN+uo4YODg3AG1j2zCe1PDa9Wtg==",
1038 | "dev": true
1039 | },
1040 | "once": {
1041 | "version": "1.4.0",
1042 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1043 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1044 | "dev": true,
1045 | "requires": {
1046 | "wrappy": "1"
1047 | }
1048 | },
1049 | "path-is-absolute": {
1050 | "version": "1.0.1",
1051 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1052 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1053 | "dev": true
1054 | },
1055 | "path-parse": {
1056 | "version": "1.0.7",
1057 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1058 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1059 | "dev": true
1060 | },
1061 | "path-type": {
1062 | "version": "4.0.0",
1063 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
1064 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
1065 | "dev": true
1066 | },
1067 | "picomatch": {
1068 | "version": "2.3.1",
1069 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1070 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1071 | "dev": true
1072 | },
1073 | "queue-microtask": {
1074 | "version": "1.2.3",
1075 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1076 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1077 | "dev": true
1078 | },
1079 | "resolve": {
1080 | "version": "1.22.1",
1081 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
1082 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
1083 | "dev": true,
1084 | "requires": {
1085 | "is-core-module": "^2.9.0",
1086 | "path-parse": "^1.0.7",
1087 | "supports-preserve-symlinks-flag": "^1.0.0"
1088 | }
1089 | },
1090 | "reusify": {
1091 | "version": "1.0.4",
1092 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1093 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
1094 | "dev": true
1095 | },
1096 | "rollup": {
1097 | "version": "2.76.0",
1098 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz",
1099 | "integrity": "sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==",
1100 | "dev": true,
1101 | "requires": {
1102 | "fsevents": "~2.3.2"
1103 | }
1104 | },
1105 | "rollup-plugin-copy": {
1106 | "version": "3.4.0",
1107 | "resolved": "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz",
1108 | "integrity": "sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ==",
1109 | "dev": true,
1110 | "requires": {
1111 | "@types/fs-extra": "^8.0.1",
1112 | "colorette": "^1.1.0",
1113 | "fs-extra": "^8.1.0",
1114 | "globby": "10.0.1",
1115 | "is-plain-object": "^3.0.0"
1116 | }
1117 | },
1118 | "run-parallel": {
1119 | "version": "1.2.0",
1120 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1121 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1122 | "dev": true,
1123 | "requires": {
1124 | "queue-microtask": "^1.2.2"
1125 | }
1126 | },
1127 | "slash": {
1128 | "version": "3.0.0",
1129 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
1130 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
1131 | "dev": true
1132 | },
1133 | "supports-preserve-symlinks-flag": {
1134 | "version": "1.0.0",
1135 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1136 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1137 | "dev": true
1138 | },
1139 | "to-regex-range": {
1140 | "version": "5.0.1",
1141 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1142 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1143 | "dev": true,
1144 | "requires": {
1145 | "is-number": "^7.0.0"
1146 | }
1147 | },
1148 | "tslib": {
1149 | "version": "2.4.0",
1150 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
1151 | "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
1152 | "dev": true
1153 | },
1154 | "typescript": {
1155 | "version": "4.7.4",
1156 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
1157 | "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
1158 | "dev": true
1159 | },
1160 | "universalify": {
1161 | "version": "0.1.2",
1162 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
1163 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
1164 | "dev": true
1165 | },
1166 | "wrappy": {
1167 | "version": "1.0.2",
1168 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1169 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1170 | "dev": true
1171 | }
1172 | }
1173 | }
1174 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "weapp-scroll",
3 | "version": "1.0.5",
4 | "description": "微信小程序带回弹效果的滚动容器,可适用在安卓、PC场景",
5 | "main": "dist/index.wxs",
6 | "miniprogram": "dist",
7 | "scripts": {
8 | "dev": "rollup -c rollup.config.js --watch",
9 | "build": "rollup -c rollup.config.js"
10 | },
11 | "keywords": [
12 | "WXS",
13 | "微信小程序",
14 | "滚动容器"
15 | ],
16 | "author": "xieyuhang",
17 | "license": "MIT",
18 | "devDependencies": {
19 | "@rollup/plugin-typescript": "^8.3.3",
20 | "miniprogram-api-typings": "^3.5.0",
21 | "rollup": "^2.76.0",
22 | "rollup-plugin-copy": "^3.4.0",
23 | "tslib": "^2.4.0",
24 | "typescript": "^4.7.4"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xieyhn/weapp-scroll/051f25f9ae8302270b4498dbdf58f0645daa02d2/preview.gif
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'rollup'
2 | import typescript from '@rollup/plugin-typescript'
3 | import copy from 'rollup-plugin-copy'
4 |
5 | export default defineConfig({
6 | input: 'src/index.ts',
7 | output: {
8 | file: 'dist/index.wxs',
9 | format: 'cjs',
10 | exports: 'default'
11 | },
12 | plugins: [
13 | typescript(),
14 | copy({
15 | targets: [
16 | { src: 'dist/index.wxs', dest: 'example/', rename: 'weapp-scroll.wxs' }
17 | ],
18 | hook: 'writeBundle'
19 | })
20 | ]
21 | })
22 |
--------------------------------------------------------------------------------
/src/Easing.ts:
--------------------------------------------------------------------------------
1 | export type EasingFunction = (t: number) => number
2 |
3 | var Easing = {
4 | v1: function (t: number) {
5 | return 1 + --t * t * t * t * t
6 | },
7 | v2: function(t: number) {
8 | return t * (2 - t)
9 | },
10 | v3: function(t: number) {
11 | return 1 - --t * t * t * t
12 | }
13 | }
14 |
15 | export default Easing
16 |
--------------------------------------------------------------------------------
/src/Utils.ts:
--------------------------------------------------------------------------------
1 | import type { Pos } from './core'
2 |
3 | var Utils = {
4 | isUndefined(val: unknown): val is undefined {
5 | return typeof val === 'undefined'
6 | },
7 |
8 | clamp(min: number, max: number, val: number) {
9 | return Math.max(min, Math.min(max, val))
10 | },
11 |
12 | clonePos(pos: Pos): Pos {
13 | return {
14 | x: pos.x,
15 | y: pos.y
16 | }
17 | },
18 |
19 | isSamePos(p1: Pos, p2: Pos) {
20 | return p1.x === p2.x && p1.y === p2.y
21 | }
22 | }
23 |
24 | export default Utils
--------------------------------------------------------------------------------
/src/core.ts:
--------------------------------------------------------------------------------
1 | import Easing, { EasingFunction } from './Easing'
2 | import Utils from './Utils'
3 | import options, { resolveOptions, Options } from './options'
4 |
5 | type Rect = WechatMiniprogram.BoundingClientRectCallbackResult
6 |
7 | export interface Pos {
8 | x: number
9 | y: number
10 | }
11 |
12 | interface ScrollCallback {
13 | (data: {
14 | x: number
15 | y: number
16 | maxScrollDistanceX: number
17 | maxScrollDistanceY: number
18 | }): void
19 | }
20 |
21 | var ownerInstance: ComponentDescriptor
22 | /**
23 | * 最外层容器 BoundingClientRect
24 | */
25 | var containerRect: Rect
26 | /**
27 | * 滑动容器实例,通过此实例设置 CSS 属性
28 | */
29 | var slidingContainerInstance: ComponentDescriptor
30 | /**
31 | * 滑动容器 BoundingClientRect
32 | */
33 | var slidingContainerRect: Rect
34 | /**
35 | * 标记 X 方向是否能滚动
36 | */
37 | var canScrollX = false
38 | /**
39 | * 标记 Y 方向是否能滚动
40 | */
41 | var canScrollY = false
42 | /**
43 | * X方向的最小、最大滚动距离。如 -200 至 0(手势往右时,元素左移,translateX 为负值)
44 | */
45 | var minTranslateX: number
46 | var maxTranslateX = 0
47 | /**
48 | * Y方向的最小,最大滚动距离。如 -200 至 0(手势往下时,元素上移,translateY 为负值)
49 | */
50 | var minTranslateY: number
51 | var maxTranslateY = 0
52 | /**
53 | * 滑动元素的位置信息,即滑动元素上的 CSS translate 值
54 | * 触摸动作需要以此为基础进行变换
55 | */
56 | var pos: Pos = { x: 0, y: 0 }
57 | /**
58 | * 记录触摸开始时,手指的位置
59 | */
60 | var startTouch = { clientX: 0, clientY: 0 }
61 | /**
62 | * 记录每次触摸开啥时,滑动容器位置
63 | */
64 | var startPos: Pos = { x: 0, y: 0 }
65 | /**
66 | * 记录触摸开始时的时间戳
67 | */
68 | var startTimeStamp = 0
69 | /**
70 | * 记录触摸开始前需要清除的 effect
71 | */
72 | var effect: (() => void) | null = null
73 |
74 | /**
75 | * callbacks
76 | */
77 | var onScrollCallbacks: ScrollCallback[] = []
78 |
79 | /**
80 | * 设置样式
81 | */
82 | function setTranslate(pos0: Pos) {
83 | if (Utils.isSamePos(pos0, pos)) return
84 |
85 | slidingContainerInstance.setStyle({
86 | transform: 'translateX(' + pos0.x + 'px) translateY(' + pos0.y + 'px)'
87 | })
88 | pos.x = pos0.x
89 | pos.y = pos0.y
90 | onScrollCallbacks.forEach(cb => cb({
91 | x: pos.x,
92 | y: pos.y,
93 | maxScrollDistanceX: minTranslateX * -1,
94 | maxScrollDistanceY: minTranslateY * -1
95 | }))
96 | }
97 |
98 | /**
99 | * @param fromPos
100 | * @param toPos
101 | * @param duration 持续时长,单位ms
102 | * @param timing
103 | * @param onComplete 动画完成的回调
104 | */
105 | function moveFromTo(
106 | fromPos: Pos,
107 | toPos: Pos,
108 | duration: number,
109 | timing: {
110 | x: EasingFunction,
111 | y: EasingFunction
112 | },
113 | onComplete?: () => void
114 | ) {
115 | var aborted = false
116 | var completed = false
117 | fromPos = Utils.clonePos(fromPos)
118 | toPos = Utils.clonePos(toPos)
119 |
120 | if (duration === 0) {
121 | setTranslate(toPos)
122 | ownerInstance.requestAnimationFrame(function() {
123 | completed = true
124 | onComplete && onComplete()
125 | })
126 | } else {
127 | var startTime = Date.now()
128 | var disX = toPos.x - fromPos.x
129 | var disY = toPos.y - fromPos.y
130 | var progressX = 1
131 | var progressY = 1
132 | var rAFHandler = function rAFHandler() {
133 | if (aborted) return
134 | var curPos = Utils.clonePos(fromPos)
135 | if (canScrollX) {
136 | progressX = timing.x(Utils.clamp(0, 1, (Date.now() - startTime) / duration))
137 | curPos.x = disX * progressX + fromPos.x
138 | }
139 | if (canScrollY) {
140 | progressY = timing.y(Utils.clamp(0, 1, (Date.now() - startTime) / duration))
141 | curPos.y = disY * progressY + fromPos.y
142 | }
143 | setTranslate(curPos)
144 |
145 | if (progressX < 1 || progressY < 1) {
146 | ownerInstance.requestAnimationFrame(rAFHandler)
147 | } else {
148 | completed = true
149 | onComplete && onComplete()
150 | }
151 | }
152 | ownerInstance.requestAnimationFrame(rAFHandler)
153 | }
154 |
155 | if (effect) effect()
156 | effect = function abort() {
157 | if (!completed && !aborted) {
158 | aborted = true
159 | }
160 | }
161 | }
162 |
163 | /**
164 | * 超出边界后就行位置修正,即回弹效果
165 | */
166 | function positionCorrection(pos: Pos) {
167 | var correctedPos: Pos = {
168 | x: Utils.clamp(minTranslateX, maxTranslateX, pos.x),
169 | y: Utils.clamp(minTranslateY, maxTranslateY, pos.y)
170 | }
171 | if (!Utils.isSamePos(correctedPos, pos)) {
172 | moveFromTo(pos, correctedPos, options.bounceDuration, { x: Easing.v3, y: Easing.v3 })
173 | }
174 | }
175 |
176 | export function setup(_options: Options, _: any, _ownerInstance: ComponentDescriptor, instance: ComponentDescriptor) {
177 | resolveOptions(_options)
178 |
179 | ownerInstance = _ownerInstance
180 | containerRect = instance.getBoundingClientRect()
181 | slidingContainerInstance = ownerInstance.selectComponent(options.slidingContainerSelector)!
182 | slidingContainerRect = slidingContainerInstance.getBoundingClientRect()
183 |
184 | if (slidingContainerRect.width > containerRect.width) {
185 | // canScrollX
186 | canScrollX = Utils.isUndefined(_options.enableScrollX) ? true : _options.enableScrollX
187 | minTranslateX = (slidingContainerRect.width - containerRect.width) * -1
188 | }
189 | if (slidingContainerRect.height > containerRect.height) {
190 | // canScrollY
191 | canScrollY = Utils.isUndefined(_options.enableScrollY) ? true : _options.enableScrollY
192 | minTranslateY = (slidingContainerRect.height - containerRect.height) * -1
193 | }
194 | }
195 |
196 | // touchstart
197 | export function touchstart(event: WechatMiniprogram.TouchEvent) {
198 | startTouch.clientX = event.changedTouches[0].clientX
199 | startTouch.clientY = event.changedTouches[0].clientY
200 |
201 | startPos.x = pos.x
202 | startPos.y = pos.y
203 |
204 | startTimeStamp = event.timeStamp
205 |
206 | if (effect) {
207 | effect()
208 | effect = null
209 | }
210 | }
211 |
212 | // touchmove
213 | export function touchmove(event: WechatMiniprogram.TouchEvent) {
214 | var deltaX = event.changedTouches[0].clientX - startTouch.clientX
215 | var deltaY = event.changedTouches[0].clientY - startTouch.clientY
216 |
217 | var x = startPos.x
218 | var y = startPos.y
219 |
220 | if (canScrollX) {
221 | x += deltaX
222 |
223 | if (x > maxTranslateX) {
224 | // 手指右滑导致元素左侧超出,超出部分添加阻尼行为
225 | x = maxTranslateX + options.damping * (x - maxTranslateX)
226 | } else if (x < minTranslateX) {
227 | // 手指左滑导致元素右侧超出,超出部分添加阻尼行为
228 | x = minTranslateX + options.damping * (x - minTranslateX)
229 | }
230 | }
231 |
232 | if (canScrollY) {
233 | y += deltaY
234 |
235 | if (y > maxTranslateY) {
236 | // 手指下滑导致元素顶部超出,超出部分添加阻尼行为
237 | y = maxTranslateY + options.damping * (y - maxTranslateY)
238 | } else if (y < minTranslateY) {
239 | // 手指上滑导致元素底部超出,超出部分添加阻尼行为
240 | y = minTranslateY + options.damping * (y - minTranslateY)
241 | }
242 | }
243 |
244 | setTranslate({ x, y })
245 | }
246 |
247 | // touchend
248 | export function touchend(event: WechatMiniprogram.TouchEvent) {
249 | var minMovingDistance = 15
250 | var maxMovingDuration = 300
251 | var finalPos: Pos = { x: pos.x, y: pos.y }
252 |
253 | // 未移动
254 | if (Utils.isSamePos(finalPos, startPos)) return
255 |
256 | var eventDuration = event.timeStamp - startTimeStamp
257 |
258 | if (eventDuration > maxMovingDuration) {
259 | positionCorrection(finalPos)
260 | return
261 | }
262 |
263 | // 移动距离
264 | var distanceX = Math.abs(finalPos.x - startPos.x)
265 | var distanceY = Math.abs(finalPos.y - startPos.y)
266 |
267 | // 动量动画持续时间
268 | var durationX = 0
269 | var durationY = 0
270 |
271 | // 动量动画函数
272 | var timingX = Easing.v1
273 | var timingY = Easing.v1
274 |
275 | var calculateMomentum = function calculateMomentum(start: number, end: number, distance: number) {
276 | var speed = distance / eventDuration
277 | var dir = end - start > 0 ? 1 : -1
278 | var duration = Math.min(options.momentumDuration, (speed * 2) / options.deceleration)
279 | var delta = Math.pow(speed, 2) / options.deceleration * dir
280 |
281 | return {
282 | duration: duration,
283 | delta: delta
284 | }
285 | }
286 |
287 | if (
288 | canScrollX
289 | && distanceX > minMovingDistance
290 | && finalPos.x <= maxTranslateX
291 | && finalPos.x >= minTranslateX
292 | ) {
293 | var result = calculateMomentum(startPos.x, pos.x, distanceX)
294 |
295 | durationX = result.duration
296 | finalPos.x += result.delta
297 |
298 | if (finalPos.x > maxTranslateX || finalPos.x < minTranslateX) {
299 | durationX = options.momentumOutBoundsDuration
300 | timingX = Easing.v2
301 | var beyondDis = containerRect.width / 6
302 | if (finalPos.x > maxTranslateX) {
303 | finalPos.x = maxTranslateX + beyondDis
304 | } else {
305 | finalPos.x = minTranslateX + beyondDis * -1
306 | }
307 | }
308 | }
309 |
310 | if (
311 | canScrollY
312 | && distanceY > minMovingDistance
313 | && finalPos.y >= minTranslateY
314 | && finalPos.y <= maxTranslateY
315 | ) {
316 | // 在边界中,可以进行动量动画
317 | var result = calculateMomentum(startPos.y, pos.y, distanceY)
318 |
319 | durationY = result.duration
320 | finalPos.y += result.delta
321 |
322 | if (finalPos.y > maxTranslateY || finalPos.y < minTranslateY) {
323 | durationY = options.momentumOutBoundsDuration
324 | timingY = Easing.v2
325 | var beyondDis = containerRect.height / 6
326 | if (finalPos.y > maxTranslateY) {
327 | finalPos.y = maxTranslateY + beyondDis
328 | } else {
329 | finalPos.y = minTranslateY + beyondDis * -1
330 | }
331 | }
332 | }
333 |
334 | moveFromTo(pos, finalPos, Math.max(durationX, durationY), { x: timingX, y: timingY }, function() {
335 | positionCorrection(finalPos)
336 | })
337 | }
338 |
339 | export function onScroll(callback: ScrollCallback) {
340 | onScrollCallbacks.push(callback)
341 |
342 | return function cancel() {
343 | var idx = onScrollCallbacks.indexOf(callback)
344 | if (idx !== 1) {
345 | onScrollCallbacks.splice(idx, 1)
346 | }
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { setup, touchstart, touchmove, touchend, onScroll } from './core'
2 |
3 | export default {
4 | setup,
5 | touchstart,
6 | touchmove,
7 | touchend,
8 | onScroll
9 | }
10 |
--------------------------------------------------------------------------------
/src/options.ts:
--------------------------------------------------------------------------------
1 | import Utils from './Utils'
2 |
3 | export interface Options {
4 | // 启用X方向滚动
5 | enableScrollX: boolean
6 | // 启用Y方向滚动
7 | enableScrollY: boolean
8 | // 滑动容器选择器
9 | slidingContainerSelector: string
10 | // 阻尼因子,超出边界后添加效果,值越小,阻力越大
11 | damping: number
12 | // 动量减速度
13 | deceleration: number
14 | // 动量动画默认的持续时间
15 | momentumDuration: number
16 | // 加上动量若超出容器后,动量动画持续时间
17 | momentumOutBoundsDuration: number
18 | // 回弹时长
19 | bounceDuration: number
20 | }
21 |
22 | var options: Options = {
23 | enableScrollX: false,
24 | enableScrollY: false,
25 | slidingContainerSelector: '.content',
26 | damping: 0.3,
27 | deceleration: 0.0015,
28 | momentumDuration: 1800,
29 | momentumOutBoundsDuration: 400,
30 | bounceDuration: 800
31 | }
32 |
33 | function setOption(userOptions: Partial, key: K) {
34 | if (!Utils.isUndefined(userOptions[key])) {
35 | options[key] = userOptions[key]!
36 | }
37 | }
38 |
39 | export function resolveOptions(userOptions: Partial) {
40 | setOption(userOptions, 'slidingContainerSelector')
41 | setOption(userOptions, 'damping')
42 | setOption(userOptions, 'bounceDuration')
43 | }
44 |
45 | export default options
46 |
--------------------------------------------------------------------------------
/src/wxs.d.ts:
--------------------------------------------------------------------------------
1 | declare interface ComponentDescriptor {
2 |
3 | selectComponent(sel: string): ComponentDescriptor | undefined
4 |
5 | selectAllComponents(sels: string[]): ComponentDescriptor[]
6 |
7 | setStyle(style: WechatMiniprogram.IAnyObject | string): void
8 |
9 | addClass(className: string): void
10 |
11 | removeClass(className: string): void
12 |
13 | hasClass(className: string): void
14 |
15 | requestAnimationFrame(cb: Function): void
16 |
17 | getBoundingClientRect(): WechatMiniprogram.BoundingClientRectCallbackResult
18 | }
19 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES3",
4 | "module": "ESNext",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitAny": true,
8 | "strictNullChecks": true,
9 | "noImplicitThis": true,
10 | "skipLibCheck": true,
11 | "baseUrl": ".",
12 | "removeComments": true,
13 | "types": [
14 | "miniprogram-api-typings"
15 | ]
16 | },
17 | "include": [
18 | "src/**/*.ts"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------