@lynx-example/scroll-coordinator 0.0.0 → 0.6.13
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 +0 -1
- package/dist/base.lynx.bundle +0 -0
- package/dist/refresh-inner.lynx.bundle +0 -0
- package/dist/refresh.lynx.bundle +0 -0
- package/dist/static/image/bg_flower.b533aa9e.gif +0 -0
- package/dist/static/image/item_0.c98eb916.jpg +0 -0
- package/dist/static/image/item_1.fe74226e.jpg +0 -0
- package/dist/static/image/item_2.d40842dd.jpg +0 -0
- package/dist/viewpager.lynx.bundle +0 -0
- package/lynx.config.mjs +33 -0
- package/package.json +31 -5
- package/src/assets/bg_flower.gif +0 -0
- package/src/assets/item_0.jpg +0 -0
- package/src/assets/item_1.jpg +0 -0
- package/src/assets/item_2.jpg +0 -0
- package/src/base/index.tsx +241 -0
- package/src/refresh/index.tsx +303 -0
- package/src/refresh-inner/index.tsx +309 -0
- package/src/viewpager/index.tsx +283 -0
- package/index.js +0 -1
package/LICENSE
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lynx.config.mjs
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { pluginQRCode } from "@lynx-js/qrcode-rsbuild-plugin";
|
|
6
|
+
import { pluginReactLynx } from "@lynx-js/react-rsbuild-plugin";
|
|
7
|
+
import { defineConfig } from "@lynx-js/rspeedy";
|
|
8
|
+
import { pluginSass } from "@rsbuild/plugin-sass";
|
|
9
|
+
import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
|
|
10
|
+
|
|
11
|
+
export default defineConfig({
|
|
12
|
+
source: {
|
|
13
|
+
entry: {
|
|
14
|
+
base: "./src/base/index.tsx",
|
|
15
|
+
refresh: "./src/refresh/index.tsx",
|
|
16
|
+
"refresh-inner": "./src/refresh-inner/index.tsx",
|
|
17
|
+
viewpager: "./src/viewpager/index.tsx",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
plugins: [
|
|
21
|
+
pluginReactLynx(),
|
|
22
|
+
pluginSass(),
|
|
23
|
+
pluginQRCode(),
|
|
24
|
+
pluginTypeCheck(),
|
|
25
|
+
],
|
|
26
|
+
output: {
|
|
27
|
+
assetPrefix: "https://lynxjs.org/lynx-examples/scroll-coordinator/dist",
|
|
28
|
+
filename: "[name].[platform].bundle",
|
|
29
|
+
},
|
|
30
|
+
environments: {
|
|
31
|
+
lynx: {},
|
|
32
|
+
},
|
|
33
|
+
});
|
package/package.json
CHANGED
|
@@ -1,9 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynx-example/scroll-coordinator",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"
|
|
3
|
+
"version": "0.6.13",
|
|
4
|
+
"description": "An example shows how to use `<scroll-coordinator>` in Lynx",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/lynx-family/lynx-examples.git",
|
|
8
|
+
"directory": "examples/scroll-coordinator"
|
|
9
|
+
},
|
|
6
10
|
"license": "Apache-2.0",
|
|
11
|
+
"author": "Lynx Authors",
|
|
7
12
|
"type": "module",
|
|
8
|
-
"
|
|
9
|
-
|
|
13
|
+
"files": [
|
|
14
|
+
"dist/",
|
|
15
|
+
"src/",
|
|
16
|
+
"lynx.config.mjs"
|
|
17
|
+
],
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"@lynx-js/react": "0.117.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@lynx-js/qrcode-rsbuild-plugin": "0.4.6",
|
|
23
|
+
"@lynx-js/react-rsbuild-plugin": "0.13.0",
|
|
24
|
+
"@lynx-js/rspeedy": "0.13.6",
|
|
25
|
+
"@lynx-js/types": "3.7.0",
|
|
26
|
+
"@rsbuild/plugin-sass": "1.5.1",
|
|
27
|
+
"@types/react": "^18.3.28",
|
|
28
|
+
"typescript": "~5.9.3"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "rspeedy build",
|
|
32
|
+
"dev": "rspeedy dev",
|
|
33
|
+
"preview": "rspeedy preview"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root } from "@lynx-js/react";
|
|
6
|
+
|
|
7
|
+
import image0 from "../assets/item_0.jpg";
|
|
8
|
+
import image1 from "../assets/item_1.jpg";
|
|
9
|
+
import image2 from "../assets/item_2.jpg";
|
|
10
|
+
|
|
11
|
+
const App = () => {
|
|
12
|
+
const coverImages = [image0, image1, image2];
|
|
13
|
+
const tabs = ["Featured", "Nearby", "Saved"];
|
|
14
|
+
const listItems = Array.from({ length: 24 }, (_, index) => {
|
|
15
|
+
return {
|
|
16
|
+
image: coverImages[index % coverImages.length],
|
|
17
|
+
title: `Scenic stop ${index + 1}`,
|
|
18
|
+
subtitle: index % 2 === 0 ? "Quiet path with a wide lookout" : "Short trail near the water",
|
|
19
|
+
tag: index % 3 === 0 ? "Fresh" : (index % 3 === 1 ? "Calm" : "Open"),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<view
|
|
25
|
+
style={{
|
|
26
|
+
width: "100%",
|
|
27
|
+
height: "100%",
|
|
28
|
+
flexDirection: "column",
|
|
29
|
+
display: "flex",
|
|
30
|
+
padding: "24px",
|
|
31
|
+
backgroundColor: "#F6F7F9",
|
|
32
|
+
boxSizing: "border-box",
|
|
33
|
+
}}
|
|
34
|
+
>
|
|
35
|
+
<text style={{ fontSize: "32px", fontWeight: "700", color: "#202124" }}>Scroll Coordinator</text>
|
|
36
|
+
<scroll-coordinator
|
|
37
|
+
style={{
|
|
38
|
+
marginTop: "24px",
|
|
39
|
+
width: "100%",
|
|
40
|
+
height: "100%",
|
|
41
|
+
flex: "1",
|
|
42
|
+
display: "flex",
|
|
43
|
+
flexDirection: "column",
|
|
44
|
+
position: "relative",
|
|
45
|
+
overflow: "hidden",
|
|
46
|
+
backgroundColor: "#EDEFF2",
|
|
47
|
+
}}
|
|
48
|
+
>
|
|
49
|
+
{
|
|
50
|
+
/*
|
|
51
|
+
Optional, fixed at the top of the scroll coordinator and won't collapse.
|
|
52
|
+
When it exists, control scroll-coordinator.height == slot.height + toolbar.height through CSS.
|
|
53
|
+
*/
|
|
54
|
+
}
|
|
55
|
+
<scroll-coordinator-toolbar
|
|
56
|
+
style={{
|
|
57
|
+
display: "flex",
|
|
58
|
+
width: "100%",
|
|
59
|
+
height: "88rpx",
|
|
60
|
+
alignItems: "center",
|
|
61
|
+
justifyContent: "space-between",
|
|
62
|
+
padding: "0 24rpx",
|
|
63
|
+
backgroundColor: "#FFFFFFAA",
|
|
64
|
+
boxSizing: "border-box",
|
|
65
|
+
}}
|
|
66
|
+
>
|
|
67
|
+
<text style={{ fontSize: "26rpx", fontWeight: "700", color: "#202124" }}>Weekend Routes</text>
|
|
68
|
+
<text style={{ fontSize: "22rpx", color: "#2D7D46" }}>3 picks</text>
|
|
69
|
+
</scroll-coordinator-toolbar>
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
/*
|
|
73
|
+
Required, it can be scrolled in scroll coordinator without affecting the layout,
|
|
74
|
+
so it is recommended to set position: absolute.
|
|
75
|
+
No need to place scroll-view or list inside.
|
|
76
|
+
*/
|
|
77
|
+
}
|
|
78
|
+
<scroll-coordinator-header
|
|
79
|
+
style={{
|
|
80
|
+
position: "absolute",
|
|
81
|
+
width: "100%",
|
|
82
|
+
height: "360rpx",
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<view
|
|
86
|
+
style={{
|
|
87
|
+
width: "100%",
|
|
88
|
+
height: "360rpx",
|
|
89
|
+
overflow: "hidden",
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<image
|
|
93
|
+
mode="aspectFill"
|
|
94
|
+
src={image0}
|
|
95
|
+
style={{
|
|
96
|
+
width: "100%",
|
|
97
|
+
height: "360rpx",
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
<view
|
|
101
|
+
style={{
|
|
102
|
+
position: "absolute",
|
|
103
|
+
left: "0",
|
|
104
|
+
bottom: "0",
|
|
105
|
+
width: "100%",
|
|
106
|
+
padding: "24rpx",
|
|
107
|
+
backgroundColor: "#00000066",
|
|
108
|
+
boxSizing: "border-box",
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
<text style={{ fontSize: "34rpx", fontWeight: "700", color: "#FFFFFF" }}>Forest Ridge</text>
|
|
112
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#FFFFFF" }}>
|
|
113
|
+
Sunrise views, shaded paths, and easy waypoints.
|
|
114
|
+
</text>
|
|
115
|
+
</view>
|
|
116
|
+
</view>
|
|
117
|
+
</scroll-coordinator-header>
|
|
118
|
+
|
|
119
|
+
{
|
|
120
|
+
/*
|
|
121
|
+
Required, its size must be the same as scroll coordinator's size.
|
|
122
|
+
If there is a toolbar, subtract its height.
|
|
123
|
+
After the header is completely collapsed, the slot will occupy the entire scroll coordinator viewport.
|
|
124
|
+
In its child nodes, scrolling can be achieved and can continue after the header is collapsed.
|
|
125
|
+
When placing scroll-view, add enable-new-nested on scroll-view to support nested scrolling interactions.
|
|
126
|
+
*/
|
|
127
|
+
}
|
|
128
|
+
<scroll-coordinator-slot
|
|
129
|
+
style={{
|
|
130
|
+
width: "100%",
|
|
131
|
+
flexDirection: "column",
|
|
132
|
+
flex: "1",
|
|
133
|
+
display: "flex",
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
{
|
|
137
|
+
/*
|
|
138
|
+
Optional sticky area. When the header is completely collapsed, it will stay at the top of the slot.
|
|
139
|
+
You can place Tabs modules or any other content here.
|
|
140
|
+
By default it accepts up and down dragging gestures. Use enable-drag to control it.
|
|
141
|
+
*/
|
|
142
|
+
}
|
|
143
|
+
<scroll-coordinator-slot-drag style={{ width: "100%" }}>
|
|
144
|
+
<view
|
|
145
|
+
style={{
|
|
146
|
+
width: "100%",
|
|
147
|
+
height: "96rpx",
|
|
148
|
+
display: "flex",
|
|
149
|
+
flexDirection: "row",
|
|
150
|
+
alignItems: "center",
|
|
151
|
+
padding: "0 16rpx",
|
|
152
|
+
backgroundColor: "#FFFFFF",
|
|
153
|
+
boxSizing: "border-box",
|
|
154
|
+
}}
|
|
155
|
+
>
|
|
156
|
+
{tabs.map((tab, index) => {
|
|
157
|
+
return (
|
|
158
|
+
<view
|
|
159
|
+
style={{
|
|
160
|
+
height: "56rpx",
|
|
161
|
+
padding: "0 20rpx",
|
|
162
|
+
marginRight: "12rpx",
|
|
163
|
+
justifyContent: "center",
|
|
164
|
+
borderRadius: "8px",
|
|
165
|
+
backgroundColor: index === 0 ? "#DDF3E5" : "#EEF1F4",
|
|
166
|
+
}}
|
|
167
|
+
>
|
|
168
|
+
<text style={{ fontSize: "22rpx", color: index === 0 ? "#1F7A4D" : "#4E5969" }}>{tab}</text>
|
|
169
|
+
</view>
|
|
170
|
+
);
|
|
171
|
+
})}
|
|
172
|
+
</view>
|
|
173
|
+
</scroll-coordinator-slot-drag>
|
|
174
|
+
<list
|
|
175
|
+
scroll-orientation="vertical"
|
|
176
|
+
list-type="single"
|
|
177
|
+
span-count={1}
|
|
178
|
+
style={{
|
|
179
|
+
width: "100%",
|
|
180
|
+
height: "100%",
|
|
181
|
+
flex: "1",
|
|
182
|
+
listMainAxisGap: "12px",
|
|
183
|
+
padding: "12px",
|
|
184
|
+
boxSizing: "border-box",
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{listItems.map((item) => {
|
|
188
|
+
return (
|
|
189
|
+
<list-item
|
|
190
|
+
item-key={item.title}
|
|
191
|
+
key={item.title}
|
|
192
|
+
>
|
|
193
|
+
<view
|
|
194
|
+
style={{
|
|
195
|
+
width: "100%",
|
|
196
|
+
height: "144rpx",
|
|
197
|
+
display: "flex",
|
|
198
|
+
flexDirection: "row",
|
|
199
|
+
alignItems: "center",
|
|
200
|
+
padding: "12rpx",
|
|
201
|
+
borderRadius: "8px",
|
|
202
|
+
backgroundColor: "#FFFFFF",
|
|
203
|
+
boxSizing: "border-box",
|
|
204
|
+
}}
|
|
205
|
+
>
|
|
206
|
+
<image
|
|
207
|
+
mode="aspectFill"
|
|
208
|
+
src={item.image}
|
|
209
|
+
style={{
|
|
210
|
+
width: "120rpx",
|
|
211
|
+
height: "120rpx",
|
|
212
|
+
borderRadius: "8px",
|
|
213
|
+
}}
|
|
214
|
+
/>
|
|
215
|
+
<view
|
|
216
|
+
style={{
|
|
217
|
+
marginLeft: "18rpx",
|
|
218
|
+
flex: 1,
|
|
219
|
+
flexDirection: "column",
|
|
220
|
+
}}
|
|
221
|
+
>
|
|
222
|
+
<text style={{ fontSize: "28rpx", fontWeight: "700", color: "#202124" }}>{item.title}</text>
|
|
223
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#5F6673" }}>{item.subtitle}</text>
|
|
224
|
+
<text style={{ marginTop: "10rpx", fontSize: "20rpx", color: "#2D7D46" }}>{item.tag}</text>
|
|
225
|
+
</view>
|
|
226
|
+
</view>
|
|
227
|
+
</list-item>
|
|
228
|
+
);
|
|
229
|
+
})}
|
|
230
|
+
</list>
|
|
231
|
+
</scroll-coordinator-slot>
|
|
232
|
+
</scroll-coordinator>
|
|
233
|
+
</view>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
root.render(<App />);
|
|
238
|
+
|
|
239
|
+
if (import.meta.webpackHot) {
|
|
240
|
+
import.meta.webpackHot.accept();
|
|
241
|
+
}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root, useRef, useState } from "@lynx-js/react";
|
|
6
|
+
import type { NodesRef } from "@lynx-js/types";
|
|
7
|
+
|
|
8
|
+
import loadingGif from "../assets/bg_flower.gif";
|
|
9
|
+
import image0 from "../assets/item_0.jpg";
|
|
10
|
+
import image1 from "../assets/item_1.jpg";
|
|
11
|
+
import image2 from "../assets/item_2.jpg";
|
|
12
|
+
|
|
13
|
+
const App = () => {
|
|
14
|
+
const refreshRef = useRef<NodesRef>(null);
|
|
15
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
16
|
+
const coverImages = [image0, image1, image2];
|
|
17
|
+
const tabs = ["Featured", "Nearby", "Saved"];
|
|
18
|
+
const listPages = ["A", "B", "C"];
|
|
19
|
+
const listItems = Array.from({ length: 24 }, (_, index) => {
|
|
20
|
+
return {
|
|
21
|
+
image: coverImages[index % coverImages.length],
|
|
22
|
+
title: `Scenic stop ${index + 1}`,
|
|
23
|
+
subtitle: index % 2 === 0 ? "Quiet path with a wide lookout" : "Short trail near the water",
|
|
24
|
+
tag: index % 3 === 0 ? "Fresh" : (index % 3 === 1 ? "Calm" : "Open"),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const onStartRefresh = () => {
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
refreshRef.current?.invoke({
|
|
31
|
+
method: "finishRefresh",
|
|
32
|
+
}).exec();
|
|
33
|
+
}, 2000);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<view
|
|
38
|
+
style={{
|
|
39
|
+
width: "100%",
|
|
40
|
+
height: "100%",
|
|
41
|
+
flexDirection: "column",
|
|
42
|
+
display: "flex",
|
|
43
|
+
padding: "24px",
|
|
44
|
+
backgroundColor: "#F6F7F9",
|
|
45
|
+
boxSizing: "border-box",
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<text style={{ fontSize: "32px", fontWeight: "700", color: "#202124" }}>Scroll Coordinator</text>
|
|
49
|
+
<refresh
|
|
50
|
+
ref={refreshRef}
|
|
51
|
+
bindstartrefresh={onStartRefresh}
|
|
52
|
+
style={{
|
|
53
|
+
marginTop: "24px",
|
|
54
|
+
width: "100%",
|
|
55
|
+
height: "100%",
|
|
56
|
+
flex: "1",
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
<refresh-header
|
|
60
|
+
style={{
|
|
61
|
+
width: "100%",
|
|
62
|
+
height: "104rpx",
|
|
63
|
+
position: "absolute",
|
|
64
|
+
justifyContent: "center",
|
|
65
|
+
alignItems: "center",
|
|
66
|
+
backgroundColor: "#F6F7F9",
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<image
|
|
70
|
+
mode="aspectFit"
|
|
71
|
+
src={loadingGif}
|
|
72
|
+
style={{
|
|
73
|
+
width: "48rpx",
|
|
74
|
+
height: "48rpx",
|
|
75
|
+
}}
|
|
76
|
+
/>
|
|
77
|
+
<text style={{ marginTop: "8rpx", fontSize: "20rpx", color: "#4E5969" }}>Refreshing routes...</text>
|
|
78
|
+
</refresh-header>
|
|
79
|
+
<scroll-coordinator
|
|
80
|
+
refresh-mode="fold"
|
|
81
|
+
style={{
|
|
82
|
+
width: "100%",
|
|
83
|
+
height: "100%",
|
|
84
|
+
flex: "1",
|
|
85
|
+
display: "flex",
|
|
86
|
+
flexDirection: "column",
|
|
87
|
+
position: "relative",
|
|
88
|
+
overflow: "hidden",
|
|
89
|
+
backgroundColor: "#EDEFF2",
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{
|
|
93
|
+
/*
|
|
94
|
+
Required, it can be scrolled in scroll coordinator without affecting the layout,
|
|
95
|
+
so it is recommended to set position: absolute.
|
|
96
|
+
No need to place scroll-view or list inside.
|
|
97
|
+
*/
|
|
98
|
+
}
|
|
99
|
+
<scroll-coordinator-header
|
|
100
|
+
style={{
|
|
101
|
+
position: "absolute",
|
|
102
|
+
width: "100%",
|
|
103
|
+
height: "360rpx",
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
<view
|
|
107
|
+
style={{
|
|
108
|
+
width: "100%",
|
|
109
|
+
height: "360rpx",
|
|
110
|
+
overflow: "hidden",
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
<image
|
|
114
|
+
mode="aspectFill"
|
|
115
|
+
src={image0}
|
|
116
|
+
style={{
|
|
117
|
+
width: "100%",
|
|
118
|
+
height: "360rpx",
|
|
119
|
+
}}
|
|
120
|
+
/>
|
|
121
|
+
<view
|
|
122
|
+
style={{
|
|
123
|
+
position: "absolute",
|
|
124
|
+
left: "0",
|
|
125
|
+
bottom: "0",
|
|
126
|
+
width: "100%",
|
|
127
|
+
padding: "24rpx",
|
|
128
|
+
backgroundColor: "#00000066",
|
|
129
|
+
boxSizing: "border-box",
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
<text style={{ fontSize: "34rpx", fontWeight: "700", color: "#FFFFFF" }}>Forest Ridge</text>
|
|
133
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#FFFFFF" }}>
|
|
134
|
+
Sunrise views, shaded paths, and easy waypoints.
|
|
135
|
+
</text>
|
|
136
|
+
</view>
|
|
137
|
+
</view>
|
|
138
|
+
</scroll-coordinator-header>
|
|
139
|
+
|
|
140
|
+
{
|
|
141
|
+
/*
|
|
142
|
+
Required, its size must be the same as scroll coordinator's size.
|
|
143
|
+
If there is a toolbar, subtract its height.
|
|
144
|
+
After the header is completely collapsed, the slot will occupy the entire scroll coordinator viewport.
|
|
145
|
+
In its child nodes, scrolling can be achieved and can continue after the header is collapsed.
|
|
146
|
+
When placing scroll-view, add enable-new-nested on scroll-view to support nested scrolling interactions.
|
|
147
|
+
*/
|
|
148
|
+
}
|
|
149
|
+
<scroll-coordinator-slot
|
|
150
|
+
style={{
|
|
151
|
+
width: "100%",
|
|
152
|
+
flexDirection: "column",
|
|
153
|
+
flex: "1",
|
|
154
|
+
display: "flex",
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
{
|
|
158
|
+
/*
|
|
159
|
+
Optional sticky area. When the header is completely collapsed, it will stay at the top of the slot.
|
|
160
|
+
You can place Tabs modules or any other content here.
|
|
161
|
+
By default it accepts up and down dragging gestures. Use enable-drag to control it.
|
|
162
|
+
*/
|
|
163
|
+
}
|
|
164
|
+
<scroll-coordinator-slot-drag style={{ width: "100%" }}>
|
|
165
|
+
<view
|
|
166
|
+
style={{
|
|
167
|
+
width: "100%",
|
|
168
|
+
height: "96rpx",
|
|
169
|
+
display: "flex",
|
|
170
|
+
flexDirection: "row",
|
|
171
|
+
alignItems: "center",
|
|
172
|
+
padding: "0 16rpx",
|
|
173
|
+
backgroundColor: "#FFFFFF",
|
|
174
|
+
boxSizing: "border-box",
|
|
175
|
+
}}
|
|
176
|
+
>
|
|
177
|
+
{tabs.map((tab, index) => {
|
|
178
|
+
const selected = currentPage === index;
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
<view
|
|
182
|
+
style={{
|
|
183
|
+
height: "56rpx",
|
|
184
|
+
padding: "0 20rpx",
|
|
185
|
+
marginRight: "12rpx",
|
|
186
|
+
justifyContent: "center",
|
|
187
|
+
borderRadius: "8px",
|
|
188
|
+
backgroundColor: selected ? "#DDF3E5" : "#EEF1F4",
|
|
189
|
+
}}
|
|
190
|
+
>
|
|
191
|
+
<text
|
|
192
|
+
style={{
|
|
193
|
+
fontSize: "22rpx",
|
|
194
|
+
fontWeight: selected ? "700" : "400",
|
|
195
|
+
color: selected ? "#1F7A4D" : "#4E5969",
|
|
196
|
+
}}
|
|
197
|
+
>
|
|
198
|
+
{tab}
|
|
199
|
+
</text>
|
|
200
|
+
</view>
|
|
201
|
+
);
|
|
202
|
+
})}
|
|
203
|
+
</view>
|
|
204
|
+
</scroll-coordinator-slot-drag>
|
|
205
|
+
<viewpager
|
|
206
|
+
style={{
|
|
207
|
+
width: "100%",
|
|
208
|
+
height: "100%",
|
|
209
|
+
flex: "1",
|
|
210
|
+
display: "flex",
|
|
211
|
+
flexDirection: "row",
|
|
212
|
+
}}
|
|
213
|
+
bindwillchange={(e) => {
|
|
214
|
+
setCurrentPage(e.detail.index);
|
|
215
|
+
}}
|
|
216
|
+
>
|
|
217
|
+
{listPages.map((page) => {
|
|
218
|
+
return (
|
|
219
|
+
<viewpager-item
|
|
220
|
+
style={{
|
|
221
|
+
width: "100%",
|
|
222
|
+
height: "100%",
|
|
223
|
+
flexShrink: 0,
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
226
|
+
<list
|
|
227
|
+
scroll-orientation="vertical"
|
|
228
|
+
list-type="single"
|
|
229
|
+
span-count={1}
|
|
230
|
+
style={{
|
|
231
|
+
width: "100%",
|
|
232
|
+
height: "100%",
|
|
233
|
+
listMainAxisGap: "12px",
|
|
234
|
+
padding: "12px",
|
|
235
|
+
boxSizing: "border-box",
|
|
236
|
+
}}
|
|
237
|
+
>
|
|
238
|
+
{listItems.map((item, index) => {
|
|
239
|
+
return (
|
|
240
|
+
<list-item
|
|
241
|
+
item-key={`list-${page}-item-${index}`}
|
|
242
|
+
key={`list-${page}-item-${index}`}
|
|
243
|
+
>
|
|
244
|
+
<view
|
|
245
|
+
style={{
|
|
246
|
+
width: "100%",
|
|
247
|
+
height: "144rpx",
|
|
248
|
+
display: "flex",
|
|
249
|
+
flexDirection: "row",
|
|
250
|
+
alignItems: "center",
|
|
251
|
+
padding: "12rpx",
|
|
252
|
+
borderRadius: "8px",
|
|
253
|
+
backgroundColor: "#FFFFFF",
|
|
254
|
+
boxSizing: "border-box",
|
|
255
|
+
}}
|
|
256
|
+
>
|
|
257
|
+
<image
|
|
258
|
+
mode="aspectFill"
|
|
259
|
+
src={item.image}
|
|
260
|
+
style={{
|
|
261
|
+
width: "120rpx",
|
|
262
|
+
height: "120rpx",
|
|
263
|
+
borderRadius: "8px",
|
|
264
|
+
}}
|
|
265
|
+
/>
|
|
266
|
+
<view
|
|
267
|
+
style={{
|
|
268
|
+
marginLeft: "18rpx",
|
|
269
|
+
flex: 1,
|
|
270
|
+
flexDirection: "column",
|
|
271
|
+
}}
|
|
272
|
+
>
|
|
273
|
+
<text style={{ fontSize: "28rpx", fontWeight: "700", color: "#202124" }}>
|
|
274
|
+
{`${item.title} ${page}`}
|
|
275
|
+
</text>
|
|
276
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#5F6673" }}>
|
|
277
|
+
{item.subtitle}
|
|
278
|
+
</text>
|
|
279
|
+
<text style={{ marginTop: "10rpx", fontSize: "20rpx", color: "#2D7D46" }}>
|
|
280
|
+
{item.tag}
|
|
281
|
+
</text>
|
|
282
|
+
</view>
|
|
283
|
+
</view>
|
|
284
|
+
</list-item>
|
|
285
|
+
);
|
|
286
|
+
})}
|
|
287
|
+
</list>
|
|
288
|
+
</viewpager-item>
|
|
289
|
+
);
|
|
290
|
+
})}
|
|
291
|
+
</viewpager>
|
|
292
|
+
</scroll-coordinator-slot>
|
|
293
|
+
</scroll-coordinator>
|
|
294
|
+
</refresh>
|
|
295
|
+
</view>
|
|
296
|
+
);
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
root.render(<App />);
|
|
300
|
+
|
|
301
|
+
if (import.meta.webpackHot) {
|
|
302
|
+
import.meta.webpackHot.accept();
|
|
303
|
+
}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root, useRef, useState } from "@lynx-js/react";
|
|
6
|
+
import type { NodesRef } from "@lynx-js/types";
|
|
7
|
+
|
|
8
|
+
import loadingGif from "../assets/bg_flower.gif";
|
|
9
|
+
import image0 from "../assets/item_0.jpg";
|
|
10
|
+
import image1 from "../assets/item_1.jpg";
|
|
11
|
+
import image2 from "../assets/item_2.jpg";
|
|
12
|
+
|
|
13
|
+
const App = () => {
|
|
14
|
+
const refreshRefs = useRef<Record<string, NodesRef | null>>({});
|
|
15
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
16
|
+
const coverImages = [image0, image1, image2];
|
|
17
|
+
const tabs = ["Featured", "Nearby", "Saved"];
|
|
18
|
+
const listPages = ["A", "B", "C"];
|
|
19
|
+
const listItems = Array.from({ length: 24 }, (_, index) => {
|
|
20
|
+
return {
|
|
21
|
+
image: coverImages[index % coverImages.length],
|
|
22
|
+
title: `Scenic stop ${index + 1}`,
|
|
23
|
+
subtitle: index % 2 === 0 ? "Quiet path with a wide lookout" : "Short trail near the water",
|
|
24
|
+
tag: index % 3 === 0 ? "Fresh" : (index % 3 === 1 ? "Calm" : "Open"),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const onStartRefresh = (page: string) => {
|
|
29
|
+
setTimeout(() => {
|
|
30
|
+
refreshRefs.current[page]?.invoke({
|
|
31
|
+
method: "finishRefresh",
|
|
32
|
+
}).exec();
|
|
33
|
+
}, 2000);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<view
|
|
38
|
+
style={{
|
|
39
|
+
width: "100%",
|
|
40
|
+
height: "100%",
|
|
41
|
+
flexDirection: "column",
|
|
42
|
+
display: "flex",
|
|
43
|
+
padding: "24px",
|
|
44
|
+
backgroundColor: "#F6F7F9",
|
|
45
|
+
boxSizing: "border-box",
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<text style={{ fontSize: "32px", fontWeight: "700", color: "#202124" }}>Scroll Coordinator</text>
|
|
49
|
+
<scroll-coordinator
|
|
50
|
+
bounces={false}
|
|
51
|
+
refresh-mode="page"
|
|
52
|
+
style={{
|
|
53
|
+
marginTop: "24px",
|
|
54
|
+
width: "100%",
|
|
55
|
+
height: "100%",
|
|
56
|
+
flex: "1",
|
|
57
|
+
display: "flex",
|
|
58
|
+
flexDirection: "column",
|
|
59
|
+
position: "relative",
|
|
60
|
+
overflow: "hidden",
|
|
61
|
+
backgroundColor: "#EDEFF2",
|
|
62
|
+
}}
|
|
63
|
+
>
|
|
64
|
+
{
|
|
65
|
+
/*
|
|
66
|
+
Required, it can be scrolled in scroll coordinator without affecting the layout,
|
|
67
|
+
so it is recommended to set position: absolute.
|
|
68
|
+
No need to place scroll-view or list inside.
|
|
69
|
+
*/
|
|
70
|
+
}
|
|
71
|
+
<scroll-coordinator-header
|
|
72
|
+
style={{
|
|
73
|
+
position: "absolute",
|
|
74
|
+
width: "100%",
|
|
75
|
+
height: "360rpx",
|
|
76
|
+
}}
|
|
77
|
+
>
|
|
78
|
+
<view
|
|
79
|
+
style={{
|
|
80
|
+
width: "100%",
|
|
81
|
+
height: "360rpx",
|
|
82
|
+
overflow: "hidden",
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
<image
|
|
86
|
+
mode="aspectFill"
|
|
87
|
+
src={image0}
|
|
88
|
+
style={{
|
|
89
|
+
width: "100%",
|
|
90
|
+
height: "360rpx",
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
<view
|
|
94
|
+
style={{
|
|
95
|
+
position: "absolute",
|
|
96
|
+
left: "0",
|
|
97
|
+
bottom: "0",
|
|
98
|
+
width: "100%",
|
|
99
|
+
padding: "24rpx",
|
|
100
|
+
backgroundColor: "#00000066",
|
|
101
|
+
boxSizing: "border-box",
|
|
102
|
+
}}
|
|
103
|
+
>
|
|
104
|
+
<text style={{ fontSize: "34rpx", fontWeight: "700", color: "#FFFFFF" }}>Forest Ridge</text>
|
|
105
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#FFFFFF" }}>
|
|
106
|
+
Sunrise views, shaded paths, and easy waypoints.
|
|
107
|
+
</text>
|
|
108
|
+
</view>
|
|
109
|
+
</view>
|
|
110
|
+
</scroll-coordinator-header>
|
|
111
|
+
|
|
112
|
+
{
|
|
113
|
+
/*
|
|
114
|
+
Required, its size must be the same as scroll coordinator's size.
|
|
115
|
+
If there is a toolbar, subtract its height.
|
|
116
|
+
After the header is completely collapsed, the slot will occupy the entire scroll coordinator viewport.
|
|
117
|
+
In its child nodes, scrolling can be achieved and can continue after the header is collapsed.
|
|
118
|
+
When placing scroll-view, add enable-new-nested on scroll-view to support nested scrolling interactions.
|
|
119
|
+
*/
|
|
120
|
+
}
|
|
121
|
+
<scroll-coordinator-slot
|
|
122
|
+
style={{
|
|
123
|
+
width: "100%",
|
|
124
|
+
flexDirection: "column",
|
|
125
|
+
flex: "1",
|
|
126
|
+
display: "flex",
|
|
127
|
+
}}
|
|
128
|
+
>
|
|
129
|
+
{
|
|
130
|
+
/*
|
|
131
|
+
Optional sticky area. When the header is completely collapsed, it will stay at the top of the slot.
|
|
132
|
+
You can place Tabs modules or any other content here.
|
|
133
|
+
By default it accepts up and down dragging gestures. Use enable-drag to control it.
|
|
134
|
+
*/
|
|
135
|
+
}
|
|
136
|
+
<scroll-coordinator-slot-drag style={{ width: "100%" }}>
|
|
137
|
+
<view
|
|
138
|
+
style={{
|
|
139
|
+
width: "100%",
|
|
140
|
+
height: "96rpx",
|
|
141
|
+
display: "flex",
|
|
142
|
+
flexDirection: "row",
|
|
143
|
+
alignItems: "center",
|
|
144
|
+
padding: "0 16rpx",
|
|
145
|
+
backgroundColor: "#FFFFFF",
|
|
146
|
+
boxSizing: "border-box",
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
{tabs.map((tab, index) => {
|
|
150
|
+
const selected = currentPage === index;
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<view
|
|
154
|
+
style={{
|
|
155
|
+
height: "56rpx",
|
|
156
|
+
padding: "0 20rpx",
|
|
157
|
+
marginRight: "12rpx",
|
|
158
|
+
justifyContent: "center",
|
|
159
|
+
borderRadius: "8px",
|
|
160
|
+
backgroundColor: selected ? "#DDF3E5" : "#EEF1F4",
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
<text
|
|
164
|
+
style={{
|
|
165
|
+
fontSize: "22rpx",
|
|
166
|
+
fontWeight: selected ? "700" : "400",
|
|
167
|
+
color: selected ? "#1F7A4D" : "#4E5969",
|
|
168
|
+
}}
|
|
169
|
+
>
|
|
170
|
+
{tab}
|
|
171
|
+
</text>
|
|
172
|
+
</view>
|
|
173
|
+
);
|
|
174
|
+
})}
|
|
175
|
+
</view>
|
|
176
|
+
</scroll-coordinator-slot-drag>
|
|
177
|
+
<viewpager
|
|
178
|
+
style={{
|
|
179
|
+
width: "100%",
|
|
180
|
+
height: "100%",
|
|
181
|
+
flex: "1",
|
|
182
|
+
display: "flex",
|
|
183
|
+
flexDirection: "row",
|
|
184
|
+
}}
|
|
185
|
+
bindwillchange={(e) => {
|
|
186
|
+
setCurrentPage(e.detail.index);
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
189
|
+
{listPages.map((page) => {
|
|
190
|
+
return (
|
|
191
|
+
<viewpager-item
|
|
192
|
+
style={{
|
|
193
|
+
width: "100%",
|
|
194
|
+
height: "100%",
|
|
195
|
+
flexShrink: 0,
|
|
196
|
+
}}
|
|
197
|
+
>
|
|
198
|
+
<refresh
|
|
199
|
+
ref={(element: NodesRef | null) => {
|
|
200
|
+
refreshRefs.current[page] = element;
|
|
201
|
+
}}
|
|
202
|
+
bindstartrefresh={() => {
|
|
203
|
+
onStartRefresh(page);
|
|
204
|
+
}}
|
|
205
|
+
style={{
|
|
206
|
+
width: "100%",
|
|
207
|
+
height: "100%",
|
|
208
|
+
}}
|
|
209
|
+
>
|
|
210
|
+
<refresh-header
|
|
211
|
+
style={{
|
|
212
|
+
width: "100%",
|
|
213
|
+
height: "104rpx",
|
|
214
|
+
position: "absolute",
|
|
215
|
+
justifyContent: "center",
|
|
216
|
+
alignItems: "center",
|
|
217
|
+
backgroundColor: "#F6F7F9",
|
|
218
|
+
}}
|
|
219
|
+
>
|
|
220
|
+
<image
|
|
221
|
+
mode="aspectFit"
|
|
222
|
+
src={loadingGif}
|
|
223
|
+
style={{
|
|
224
|
+
width: "48rpx",
|
|
225
|
+
height: "48rpx",
|
|
226
|
+
}}
|
|
227
|
+
/>
|
|
228
|
+
<text style={{ marginTop: "8rpx", fontSize: "20rpx", color: "#4E5969" }}>
|
|
229
|
+
Refreshing routes...
|
|
230
|
+
</text>
|
|
231
|
+
</refresh-header>
|
|
232
|
+
<list
|
|
233
|
+
scroll-orientation="vertical"
|
|
234
|
+
list-type="single"
|
|
235
|
+
span-count={1}
|
|
236
|
+
style={{
|
|
237
|
+
width: "100%",
|
|
238
|
+
height: "100%",
|
|
239
|
+
listMainAxisGap: "12px",
|
|
240
|
+
padding: "12px",
|
|
241
|
+
boxSizing: "border-box",
|
|
242
|
+
}}
|
|
243
|
+
>
|
|
244
|
+
{listItems.map((item, index) => {
|
|
245
|
+
return (
|
|
246
|
+
<list-item
|
|
247
|
+
item-key={`list-${page}-item-${index}`}
|
|
248
|
+
key={`list-${page}-item-${index}`}
|
|
249
|
+
>
|
|
250
|
+
<view
|
|
251
|
+
style={{
|
|
252
|
+
width: "100%",
|
|
253
|
+
height: "144rpx",
|
|
254
|
+
display: "flex",
|
|
255
|
+
flexDirection: "row",
|
|
256
|
+
alignItems: "center",
|
|
257
|
+
padding: "12rpx",
|
|
258
|
+
borderRadius: "8px",
|
|
259
|
+
backgroundColor: "#FFFFFF",
|
|
260
|
+
boxSizing: "border-box",
|
|
261
|
+
}}
|
|
262
|
+
>
|
|
263
|
+
<image
|
|
264
|
+
mode="aspectFill"
|
|
265
|
+
src={item.image}
|
|
266
|
+
style={{
|
|
267
|
+
width: "120rpx",
|
|
268
|
+
height: "120rpx",
|
|
269
|
+
borderRadius: "8px",
|
|
270
|
+
}}
|
|
271
|
+
/>
|
|
272
|
+
<view
|
|
273
|
+
style={{
|
|
274
|
+
marginLeft: "18rpx",
|
|
275
|
+
flex: 1,
|
|
276
|
+
flexDirection: "column",
|
|
277
|
+
}}
|
|
278
|
+
>
|
|
279
|
+
<text style={{ fontSize: "28rpx", fontWeight: "700", color: "#202124" }}>
|
|
280
|
+
{`${item.title} ${page}`}
|
|
281
|
+
</text>
|
|
282
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#5F6673" }}>
|
|
283
|
+
{item.subtitle}
|
|
284
|
+
</text>
|
|
285
|
+
<text style={{ marginTop: "10rpx", fontSize: "20rpx", color: "#2D7D46" }}>
|
|
286
|
+
{item.tag}
|
|
287
|
+
</text>
|
|
288
|
+
</view>
|
|
289
|
+
</view>
|
|
290
|
+
</list-item>
|
|
291
|
+
);
|
|
292
|
+
})}
|
|
293
|
+
</list>
|
|
294
|
+
</refresh>
|
|
295
|
+
</viewpager-item>
|
|
296
|
+
);
|
|
297
|
+
})}
|
|
298
|
+
</viewpager>
|
|
299
|
+
</scroll-coordinator-slot>
|
|
300
|
+
</scroll-coordinator>
|
|
301
|
+
</view>
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
root.render(<App />);
|
|
306
|
+
|
|
307
|
+
if (import.meta.webpackHot) {
|
|
308
|
+
import.meta.webpackHot.accept();
|
|
309
|
+
}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
// Copyright 2024 The Lynx Authors. All rights reserved.
|
|
2
|
+
// Licensed under the Apache License Version 2.0 that can be found in the
|
|
3
|
+
// LICENSE file in the root directory of this source tree.
|
|
4
|
+
|
|
5
|
+
import { root, useState } from "@lynx-js/react";
|
|
6
|
+
|
|
7
|
+
import image0 from "../assets/item_0.jpg";
|
|
8
|
+
import image1 from "../assets/item_1.jpg";
|
|
9
|
+
import image2 from "../assets/item_2.jpg";
|
|
10
|
+
|
|
11
|
+
const App = () => {
|
|
12
|
+
const [currentPage, setCurrentPage] = useState(0);
|
|
13
|
+
const coverImages = [image0, image1, image2];
|
|
14
|
+
const tabs = ["Featured", "Nearby", "Saved"];
|
|
15
|
+
const listPages = ["A", "B", "C"];
|
|
16
|
+
const listItems = Array.from({ length: 24 }, (_, index) => {
|
|
17
|
+
return {
|
|
18
|
+
image: coverImages[index % coverImages.length],
|
|
19
|
+
title: `Scenic stop ${index + 1}`,
|
|
20
|
+
subtitle: index % 2 === 0 ? "Quiet path with a wide lookout" : "Short trail near the water",
|
|
21
|
+
tag: index % 3 === 0 ? "Fresh" : (index % 3 === 1 ? "Calm" : "Open"),
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<view
|
|
27
|
+
style={{
|
|
28
|
+
width: "100%",
|
|
29
|
+
height: "100%",
|
|
30
|
+
flexDirection: "column",
|
|
31
|
+
display: "flex",
|
|
32
|
+
padding: "24px",
|
|
33
|
+
backgroundColor: "#F6F7F9",
|
|
34
|
+
boxSizing: "border-box",
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
<text style={{ fontSize: "32px", fontWeight: "700", color: "#202124" }}>Scroll Coordinator</text>
|
|
38
|
+
<scroll-coordinator
|
|
39
|
+
style={{
|
|
40
|
+
marginTop: "24px",
|
|
41
|
+
width: "100%",
|
|
42
|
+
height: "100%",
|
|
43
|
+
flex: "1",
|
|
44
|
+
display: "flex",
|
|
45
|
+
flexDirection: "column",
|
|
46
|
+
position: "relative",
|
|
47
|
+
overflow: "hidden",
|
|
48
|
+
backgroundColor: "#EDEFF2",
|
|
49
|
+
}}
|
|
50
|
+
>
|
|
51
|
+
{
|
|
52
|
+
/*
|
|
53
|
+
Optional, fixed at the top of the scroll coordinator and won't collapse.
|
|
54
|
+
When it exists, control scroll-coordinator.height == slot.height + toolbar.height through CSS.
|
|
55
|
+
*/
|
|
56
|
+
}
|
|
57
|
+
<scroll-coordinator-toolbar
|
|
58
|
+
style={{
|
|
59
|
+
display: "flex",
|
|
60
|
+
width: "100%",
|
|
61
|
+
height: "88rpx",
|
|
62
|
+
alignItems: "center",
|
|
63
|
+
justifyContent: "space-between",
|
|
64
|
+
padding: "0 24rpx",
|
|
65
|
+
backgroundColor: "#FFFFFFAA",
|
|
66
|
+
boxSizing: "border-box",
|
|
67
|
+
}}
|
|
68
|
+
>
|
|
69
|
+
<text style={{ fontSize: "26rpx", fontWeight: "700", color: "#202124" }}>Weekend Routes</text>
|
|
70
|
+
<text style={{ fontSize: "22rpx", color: "#2D7D46" }}>3 lists</text>
|
|
71
|
+
</scroll-coordinator-toolbar>
|
|
72
|
+
|
|
73
|
+
{
|
|
74
|
+
/*
|
|
75
|
+
Required, it can be scrolled in scroll coordinator without affecting the layout,
|
|
76
|
+
so it is recommended to set position: absolute.
|
|
77
|
+
No need to place scroll-view or list inside.
|
|
78
|
+
*/
|
|
79
|
+
}
|
|
80
|
+
<scroll-coordinator-header
|
|
81
|
+
style={{
|
|
82
|
+
position: "absolute",
|
|
83
|
+
width: "100%",
|
|
84
|
+
height: "360rpx",
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<view
|
|
88
|
+
style={{
|
|
89
|
+
width: "100%",
|
|
90
|
+
height: "360rpx",
|
|
91
|
+
overflow: "hidden",
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
<image
|
|
95
|
+
mode="aspectFill"
|
|
96
|
+
src={image0}
|
|
97
|
+
style={{
|
|
98
|
+
width: "100%",
|
|
99
|
+
height: "360rpx",
|
|
100
|
+
}}
|
|
101
|
+
/>
|
|
102
|
+
<view
|
|
103
|
+
style={{
|
|
104
|
+
position: "absolute",
|
|
105
|
+
left: "0",
|
|
106
|
+
bottom: "0",
|
|
107
|
+
width: "100%",
|
|
108
|
+
padding: "24rpx",
|
|
109
|
+
backgroundColor: "#00000066",
|
|
110
|
+
boxSizing: "border-box",
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
<text style={{ fontSize: "34rpx", fontWeight: "700", color: "#FFFFFF" }}>Forest Ridge</text>
|
|
114
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#FFFFFF" }}>
|
|
115
|
+
Sunrise views, shaded paths, and easy waypoints.
|
|
116
|
+
</text>
|
|
117
|
+
</view>
|
|
118
|
+
</view>
|
|
119
|
+
</scroll-coordinator-header>
|
|
120
|
+
|
|
121
|
+
{
|
|
122
|
+
/*
|
|
123
|
+
Required, its size must be the same as scroll coordinator's size.
|
|
124
|
+
If there is a toolbar, subtract its height.
|
|
125
|
+
After the header is completely collapsed, the slot will occupy the entire scroll coordinator viewport.
|
|
126
|
+
In its child nodes, scrolling can be achieved and can continue after the header is collapsed.
|
|
127
|
+
When placing scroll-view, add enable-new-nested on scroll-view to support nested scrolling interactions.
|
|
128
|
+
*/
|
|
129
|
+
}
|
|
130
|
+
<scroll-coordinator-slot
|
|
131
|
+
style={{
|
|
132
|
+
width: "100%",
|
|
133
|
+
flexDirection: "column",
|
|
134
|
+
flex: "1",
|
|
135
|
+
display: "flex",
|
|
136
|
+
}}
|
|
137
|
+
>
|
|
138
|
+
{
|
|
139
|
+
/*
|
|
140
|
+
Optional sticky area. When the header is completely collapsed, it will stay at the top of the slot.
|
|
141
|
+
You can place Tabs modules or any other content here.
|
|
142
|
+
By default it accepts up and down dragging gestures. Use enable-drag to control it.
|
|
143
|
+
*/
|
|
144
|
+
}
|
|
145
|
+
<scroll-coordinator-slot-drag style={{ width: "100%" }}>
|
|
146
|
+
<view
|
|
147
|
+
style={{
|
|
148
|
+
width: "100%",
|
|
149
|
+
height: "96rpx",
|
|
150
|
+
display: "flex",
|
|
151
|
+
flexDirection: "row",
|
|
152
|
+
alignItems: "center",
|
|
153
|
+
padding: "0 16rpx",
|
|
154
|
+
backgroundColor: "#FFFFFF",
|
|
155
|
+
boxSizing: "border-box",
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
{tabs.map((tab, index) => {
|
|
159
|
+
const selected = currentPage === index;
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<view
|
|
163
|
+
style={{
|
|
164
|
+
height: "56rpx",
|
|
165
|
+
padding: "0 20rpx",
|
|
166
|
+
marginRight: "12rpx",
|
|
167
|
+
justifyContent: "center",
|
|
168
|
+
borderRadius: "8px",
|
|
169
|
+
backgroundColor: selected ? "#DDF3E5" : "#EEF1F4",
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<text
|
|
173
|
+
style={{
|
|
174
|
+
fontSize: "22rpx",
|
|
175
|
+
fontWeight: selected ? "700" : "400",
|
|
176
|
+
color: selected ? "#1F7A4D" : "#4E5969",
|
|
177
|
+
}}
|
|
178
|
+
>
|
|
179
|
+
{tab}
|
|
180
|
+
</text>
|
|
181
|
+
</view>
|
|
182
|
+
);
|
|
183
|
+
})}
|
|
184
|
+
</view>
|
|
185
|
+
</scroll-coordinator-slot-drag>
|
|
186
|
+
<viewpager
|
|
187
|
+
style={{
|
|
188
|
+
width: "100%",
|
|
189
|
+
height: "100%",
|
|
190
|
+
flex: "1",
|
|
191
|
+
display: "flex",
|
|
192
|
+
flexDirection: "row",
|
|
193
|
+
}}
|
|
194
|
+
bindwillchange={(e) => {
|
|
195
|
+
setCurrentPage(e.detail.index);
|
|
196
|
+
}}
|
|
197
|
+
>
|
|
198
|
+
{listPages.map((page) => {
|
|
199
|
+
return (
|
|
200
|
+
<viewpager-item
|
|
201
|
+
style={{
|
|
202
|
+
width: "100%",
|
|
203
|
+
height: "100%",
|
|
204
|
+
flexShrink: 0,
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
207
|
+
<list
|
|
208
|
+
scroll-orientation="vertical"
|
|
209
|
+
list-type="single"
|
|
210
|
+
span-count={1}
|
|
211
|
+
style={{
|
|
212
|
+
width: "100%",
|
|
213
|
+
height: "100%",
|
|
214
|
+
listMainAxisGap: "12px",
|
|
215
|
+
padding: "12px",
|
|
216
|
+
boxSizing: "border-box",
|
|
217
|
+
}}
|
|
218
|
+
>
|
|
219
|
+
{listItems.map((item, index) => {
|
|
220
|
+
return (
|
|
221
|
+
<list-item
|
|
222
|
+
item-key={`list-${page}-item-${index}`}
|
|
223
|
+
key={`list-${page}-item-${index}`}
|
|
224
|
+
>
|
|
225
|
+
<view
|
|
226
|
+
style={{
|
|
227
|
+
width: "100%",
|
|
228
|
+
height: "144rpx",
|
|
229
|
+
display: "flex",
|
|
230
|
+
flexDirection: "row",
|
|
231
|
+
alignItems: "center",
|
|
232
|
+
padding: "12rpx",
|
|
233
|
+
borderRadius: "8px",
|
|
234
|
+
backgroundColor: "#FFFFFF",
|
|
235
|
+
boxSizing: "border-box",
|
|
236
|
+
}}
|
|
237
|
+
>
|
|
238
|
+
<image
|
|
239
|
+
mode="aspectFill"
|
|
240
|
+
src={item.image}
|
|
241
|
+
style={{
|
|
242
|
+
width: "120rpx",
|
|
243
|
+
height: "120rpx",
|
|
244
|
+
borderRadius: "8px",
|
|
245
|
+
}}
|
|
246
|
+
/>
|
|
247
|
+
<view
|
|
248
|
+
style={{
|
|
249
|
+
marginLeft: "18rpx",
|
|
250
|
+
flex: 1,
|
|
251
|
+
flexDirection: "column",
|
|
252
|
+
}}
|
|
253
|
+
>
|
|
254
|
+
<text style={{ fontSize: "28rpx", fontWeight: "700", color: "#202124" }}>
|
|
255
|
+
{`${item.title} ${page}`}
|
|
256
|
+
</text>
|
|
257
|
+
<text style={{ marginTop: "8rpx", fontSize: "22rpx", color: "#5F6673" }}>
|
|
258
|
+
{item.subtitle}
|
|
259
|
+
</text>
|
|
260
|
+
<text style={{ marginTop: "10rpx", fontSize: "20rpx", color: "#2D7D46" }}>
|
|
261
|
+
{item.tag}
|
|
262
|
+
</text>
|
|
263
|
+
</view>
|
|
264
|
+
</view>
|
|
265
|
+
</list-item>
|
|
266
|
+
);
|
|
267
|
+
})}
|
|
268
|
+
</list>
|
|
269
|
+
</viewpager-item>
|
|
270
|
+
);
|
|
271
|
+
})}
|
|
272
|
+
</viewpager>
|
|
273
|
+
</scroll-coordinator-slot>
|
|
274
|
+
</scroll-coordinator>
|
|
275
|
+
</view>
|
|
276
|
+
);
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
root.render(<App />);
|
|
280
|
+
|
|
281
|
+
if (import.meta.webpackHot) {
|
|
282
|
+
import.meta.webpackHot.accept();
|
|
283
|
+
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {}
|