@lynx-example/lynx-ui-scroll-view 0.0.16 → 0.0.17
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/CHANGELOG.md +7 -0
- package/NativeUseBounces/index.css +136 -0
- package/NativeUseBounces/index.tsx +155 -0
- package/dist/ScrollViewBasic.lynx.bundle +0 -0
- package/dist/ScrollViewBounces.lynx.bundle +0 -0
- package/dist/ScrollViewBouncesRTL.lynx.bundle +0 -0
- package/dist/ScrollViewInnerFlex.lynx.bundle +0 -0
- package/dist/ScrollViewNativeUseBounces.lynx.bundle +0 -0
- package/dist/ScrollViewZIndex.lynx.bundle +0 -0
- package/lynx.config.mjs +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
@import "@lynx-js/luna-styles/index.css";
|
|
2
|
+
|
|
3
|
+
.demo-container {
|
|
4
|
+
width: 100%;
|
|
5
|
+
height: 100%;
|
|
6
|
+
padding: 36px 24px 24px;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
align-items: center;
|
|
10
|
+
background-color: var(--canvas);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.header {
|
|
14
|
+
width: 100%;
|
|
15
|
+
margin-bottom: 20px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.title {
|
|
19
|
+
color: var(--content);
|
|
20
|
+
font-size: 28px;
|
|
21
|
+
font-weight: 700;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.description {
|
|
25
|
+
color: var(--content-subtle);
|
|
26
|
+
font-size: 14px;
|
|
27
|
+
margin-top: 6px;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.metrics {
|
|
31
|
+
width: 100%;
|
|
32
|
+
margin-top: 14px;
|
|
33
|
+
padding: 12px;
|
|
34
|
+
display: flex;
|
|
35
|
+
flex-direction: row;
|
|
36
|
+
flex-wrap: wrap;
|
|
37
|
+
gap: 8px;
|
|
38
|
+
border-radius: 12px;
|
|
39
|
+
background-color: var(--paper);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.metric {
|
|
43
|
+
color: var(--content-subtle);
|
|
44
|
+
font-size: 12px;
|
|
45
|
+
padding: 6px 8px;
|
|
46
|
+
border-radius: 8px;
|
|
47
|
+
background-color: var(--canvas);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.metric--event {
|
|
51
|
+
color: var(--primary);
|
|
52
|
+
font-weight: 600;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.scroll-view {
|
|
56
|
+
background-color: var(--paper);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.scroll-content {
|
|
60
|
+
width: 100%;
|
|
61
|
+
padding: 14px;
|
|
62
|
+
display: flex;
|
|
63
|
+
flex-direction: column;
|
|
64
|
+
gap: 12px;
|
|
65
|
+
background: linear-gradient(
|
|
66
|
+
180deg,
|
|
67
|
+
var(--gradient-a),
|
|
68
|
+
var(--gradient-b),
|
|
69
|
+
var(--gradient-c),
|
|
70
|
+
var(--gradient-d)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.card {
|
|
75
|
+
width: 100%;
|
|
76
|
+
height: 88px;
|
|
77
|
+
padding: 14px 18px;
|
|
78
|
+
display: flex;
|
|
79
|
+
flex-direction: row;
|
|
80
|
+
align-items: center;
|
|
81
|
+
border-radius: 16px;
|
|
82
|
+
background-color: var(--canvas);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.card__index {
|
|
86
|
+
width: 52px;
|
|
87
|
+
color: var(--primary);
|
|
88
|
+
font-size: 32px;
|
|
89
|
+
font-weight: 700;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.card__copy {
|
|
93
|
+
display: flex;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.card__title {
|
|
98
|
+
color: var(--content);
|
|
99
|
+
font-size: 16px;
|
|
100
|
+
font-weight: 600;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.card__subtitle {
|
|
104
|
+
color: var(--content-subtle);
|
|
105
|
+
font-size: 12px;
|
|
106
|
+
margin-top: 4px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.bounce-item {
|
|
110
|
+
width: 100%;
|
|
111
|
+
height: 96px;
|
|
112
|
+
display: flex;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
align-items: center;
|
|
115
|
+
justify-content: center;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.bounce-item--upper {
|
|
119
|
+
background-color: var(--primary);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.bounce-item--lower {
|
|
123
|
+
background-color: var(--primary-2);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.bounce-item__label {
|
|
127
|
+
color: var(--gradient-content);
|
|
128
|
+
font-size: 16px;
|
|
129
|
+
font-weight: 700;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.bounce-item__hint {
|
|
133
|
+
color: var(--gradient-content);
|
|
134
|
+
font-size: 12px;
|
|
135
|
+
margin-top: 4px;
|
|
136
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
// Copyright 2026 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 { ScrollView } from '@lynx-js/lynx-ui'
|
|
8
|
+
import type { ScrollEvent } from '@lynx-js/types'
|
|
9
|
+
|
|
10
|
+
import './index.css'
|
|
11
|
+
|
|
12
|
+
const VIEWPORT_HEIGHT = 420
|
|
13
|
+
const TRIGGER_DISTANCE = 48
|
|
14
|
+
const ITEMS = Array.from({ length: 12 }, (_, index) => index + 1)
|
|
15
|
+
|
|
16
|
+
interface Metrics {
|
|
17
|
+
bounceCount: number
|
|
18
|
+
lastBounce: 'none' | 'upper' | 'lower'
|
|
19
|
+
maxLowerDistance: number
|
|
20
|
+
maxUpperDistance: number
|
|
21
|
+
minScrollTop: number
|
|
22
|
+
scrollHeight: number
|
|
23
|
+
scrollTop: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function BounceItem(props: {
|
|
27
|
+
direction: 'upper' | 'lower'
|
|
28
|
+
label: string
|
|
29
|
+
}) {
|
|
30
|
+
const { direction, label } = props
|
|
31
|
+
return (
|
|
32
|
+
<view className={`bounce-item bounce-item--${direction}`}>
|
|
33
|
+
<text className='bounce-item__label'>{label}</text>
|
|
34
|
+
<text className='bounce-item__hint'>Threshold: 48px</text>
|
|
35
|
+
</view>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function formatMetric(value: number) {
|
|
40
|
+
return Number.isFinite(value) ? value.toFixed(1) : '--'
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function App() {
|
|
44
|
+
const [metrics, setMetrics] = useState<Metrics>({
|
|
45
|
+
bounceCount: 0,
|
|
46
|
+
lastBounce: 'none',
|
|
47
|
+
maxLowerDistance: 0,
|
|
48
|
+
maxUpperDistance: 0,
|
|
49
|
+
minScrollTop: 0,
|
|
50
|
+
scrollHeight: 0,
|
|
51
|
+
scrollTop: 0,
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const handleScroll = (event: ScrollEvent) => {
|
|
55
|
+
const { scrollHeight, scrollTop } = event.detail
|
|
56
|
+
const upperDistance = Math.max(0, -scrollTop)
|
|
57
|
+
const lowerDistance = Math.max(0, scrollTop - scrollHeight)
|
|
58
|
+
|
|
59
|
+
setMetrics(previous => ({
|
|
60
|
+
...previous,
|
|
61
|
+
maxLowerDistance: Math.max(
|
|
62
|
+
previous.maxLowerDistance,
|
|
63
|
+
lowerDistance,
|
|
64
|
+
),
|
|
65
|
+
maxUpperDistance: Math.max(
|
|
66
|
+
previous.maxUpperDistance,
|
|
67
|
+
upperDistance,
|
|
68
|
+
),
|
|
69
|
+
minScrollTop: Math.min(previous.minScrollTop, scrollTop),
|
|
70
|
+
scrollHeight,
|
|
71
|
+
scrollTop,
|
|
72
|
+
}))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<view className='demo-container lunaris-dark'>
|
|
77
|
+
<view className='header'>
|
|
78
|
+
<text className='title'>Native useBounces</text>
|
|
79
|
+
<text className='description'>
|
|
80
|
+
Pull beyond both edges and watch bindscroll metrics.
|
|
81
|
+
</text>
|
|
82
|
+
<view className='metrics'>
|
|
83
|
+
<text className='metric'>
|
|
84
|
+
{`scrollTop: ${formatMetric(metrics.scrollTop)}`}
|
|
85
|
+
</text>
|
|
86
|
+
<text className='metric'>
|
|
87
|
+
{`min scrollTop: ${formatMetric(metrics.minScrollTop)}`}
|
|
88
|
+
</text>
|
|
89
|
+
<text className='metric'>
|
|
90
|
+
{`max upper: ${formatMetric(metrics.maxUpperDistance)}`}
|
|
91
|
+
</text>
|
|
92
|
+
<text className='metric'>
|
|
93
|
+
{`max lower: ${formatMetric(metrics.maxLowerDistance)}`}
|
|
94
|
+
</text>
|
|
95
|
+
<text className='metric'>
|
|
96
|
+
{`scrollHeight: ${formatMetric(metrics.scrollHeight)}`}
|
|
97
|
+
</text>
|
|
98
|
+
<text className='metric metric--event'>
|
|
99
|
+
{`bounce event: ${metrics.lastBounce} (${metrics.bounceCount})`}
|
|
100
|
+
</text>
|
|
101
|
+
</view>
|
|
102
|
+
</view>
|
|
103
|
+
|
|
104
|
+
<ScrollView
|
|
105
|
+
enableNewArch={true}
|
|
106
|
+
scrollOrientation='vertical'
|
|
107
|
+
className='scroll-view'
|
|
108
|
+
style={{
|
|
109
|
+
width: '100%',
|
|
110
|
+
height: `${VIEWPORT_HEIGHT}px`,
|
|
111
|
+
borderRadius: '20px',
|
|
112
|
+
}}
|
|
113
|
+
onScroll={handleScroll}
|
|
114
|
+
bounceableOptions={{
|
|
115
|
+
enableBounces: true,
|
|
116
|
+
alwaysBouncing: true,
|
|
117
|
+
singleSidedBounce: 'both',
|
|
118
|
+
startBounceTriggerDistance: TRIGGER_DISTANCE,
|
|
119
|
+
endBounceTriggerDistance: TRIGGER_DISTANCE,
|
|
120
|
+
upperBounceItem: (
|
|
121
|
+
<BounceItem direction='upper' label='Native upper bounce' />
|
|
122
|
+
),
|
|
123
|
+
lowerBounceItem: (
|
|
124
|
+
<BounceItem direction='lower' label='Native lower bounce' />
|
|
125
|
+
),
|
|
126
|
+
onScrollToBounces: ({ direction }) => {
|
|
127
|
+
setMetrics(previous => ({
|
|
128
|
+
...previous,
|
|
129
|
+
bounceCount: previous.bounceCount + 1,
|
|
130
|
+
lastBounce: direction,
|
|
131
|
+
}))
|
|
132
|
+
},
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
<view className='scroll-content'>
|
|
136
|
+
{ITEMS.map(item => (
|
|
137
|
+
<view className='card' key={`native-bounce-card-${item}`}>
|
|
138
|
+
<text className='card__index'>{`${item}`}</text>
|
|
139
|
+
<view className='card__copy'>
|
|
140
|
+
<text className='card__title'>Native ScrollView</text>
|
|
141
|
+
<text className='card__subtitle'>
|
|
142
|
+
scroll-view-new-arch=true
|
|
143
|
+
</text>
|
|
144
|
+
</view>
|
|
145
|
+
</view>
|
|
146
|
+
))}
|
|
147
|
+
</view>
|
|
148
|
+
</ScrollView>
|
|
149
|
+
</view>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
root.render(<App />)
|
|
154
|
+
|
|
155
|
+
export default App
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/lynx.config.mjs
CHANGED
|
@@ -9,6 +9,7 @@ const defaultConfig = exampleConfig({
|
|
|
9
9
|
ScrollViewBounces: './Bounces/index.tsx',
|
|
10
10
|
ScrollViewBouncesRTL: './BouncesRTL/index.tsx',
|
|
11
11
|
ScrollViewInnerFlex: './InnerFlex/index.tsx',
|
|
12
|
+
ScrollViewNativeUseBounces: './NativeUseBounces/index.tsx',
|
|
12
13
|
ScrollViewScrollBy: './ScrollBy/index.tsx',
|
|
13
14
|
ScrollViewZIndex: './ZIndex/index.tsx',
|
|
14
15
|
}, { needWeb: false })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lynx-example/lynx-ui-scroll-view",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"description": "Example app demonstrating ScrollView usage in lynx-ui",
|
|
5
5
|
"homepage": "https://github.com/lynx-family/lynx-ui/tree/main/apps/examples/ScrollView#readme",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@lynx-js/react": "0.123.1",
|
|
27
27
|
"clsx": "^2.1.1",
|
|
28
28
|
"@lynx-js/luna-styles": "0.2.2",
|
|
29
|
-
"@lynx-js/lynx-ui": "3.
|
|
29
|
+
"@lynx-js/lynx-ui": "3.137.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@lynx-js/qrcode-rsbuild-plugin": "0.6.0",
|