@lynx-example/lynx-ui-swiper 0.0.1 → 0.0.2

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.
Files changed (62) hide show
  1. package/Basic/index.tsx +109 -0
  2. package/Basic/styles.css +49 -0
  3. package/BasicDynamic/index.tsx +130 -0
  4. package/BasicDynamic/styles.css +47 -0
  5. package/BasicUpdateSize/index.tsx +131 -0
  6. package/BasicUpdateSize/styles.css +47 -0
  7. package/Bounces/index.tsx +73 -0
  8. package/Bounces/styles.css +41 -0
  9. package/CHANGELOG.md +8 -0
  10. package/Common/Button/index.tsx +48 -0
  11. package/Common/Button/styles.css +41 -0
  12. package/Common/Card/index.tsx +21 -0
  13. package/Common/Card/styles.css +21 -0
  14. package/Common/Indicator/index.tsx +24 -0
  15. package/Common/Indicator/styles.css +21 -0
  16. package/Custom/index.tsx +87 -0
  17. package/Custom/styles.css +47 -0
  18. package/CustomScale/index.tsx +116 -0
  19. package/CustomScale/styles.css +41 -0
  20. package/CustomTinder/Card.tsx +24 -0
  21. package/CustomTinder/index.tsx +111 -0
  22. package/CustomTinder/styles.css +61 -0
  23. package/DifferentHeight/Button.tsx +33 -0
  24. package/DifferentHeight/index.tsx +95 -0
  25. package/DifferentHeight/styles.css +50 -0
  26. package/Direction/index.tsx +127 -0
  27. package/Direction/styles.css +41 -0
  28. package/EmptyDataBug/index.tsx +371 -0
  29. package/EmptyDataBug/styles.css +75 -0
  30. package/Indicator/index.tsx +67 -0
  31. package/Indicator/styles.css +41 -0
  32. package/Lazy/index.tsx +83 -0
  33. package/Lazy/styles.css +41 -0
  34. package/Loop/index.tsx +77 -0
  35. package/Loop/styles.css +41 -0
  36. package/RTL/Button.tsx +33 -0
  37. package/RTL/index.tsx +133 -0
  38. package/RTL/styles.css +41 -0
  39. package/RTLCustom/index.tsx +115 -0
  40. package/RTLCustom/styles.css +41 -0
  41. package/RTLLoop/Button.tsx +33 -0
  42. package/RTLLoop/index.tsx +116 -0
  43. package/RTLLoop/styles.css +41 -0
  44. package/RTLLoopLynxRTL/Button.tsx +33 -0
  45. package/RTLLoopLynxRTL/index.tsx +116 -0
  46. package/RTLLoopLynxRTL/styles.css +41 -0
  47. package/WithGap/Button.tsx +33 -0
  48. package/WithGap/index.tsx +118 -0
  49. package/WithGap/styles.css +47 -0
  50. package/dist/SwiperBasic.lynx.bundle +0 -0
  51. package/dist/SwiperBasic.web.bundle +1 -1
  52. package/dist/SwiperBasicDynamic.lynx.bundle +0 -0
  53. package/dist/SwiperBasicDynamic.web.bundle +1 -1
  54. package/dist/SwiperBasicUpdateSize.lynx.bundle +0 -0
  55. package/dist/SwiperBasicUpdateSize.web.bundle +1 -1
  56. package/dist/SwiperCustomTinder.lynx.bundle +0 -0
  57. package/dist/SwiperCustomTinder.web.bundle +1 -1
  58. package/dist/SwiperDifferentHeight.lynx.bundle +0 -0
  59. package/dist/SwiperDifferentHeight.web.bundle +1 -1
  60. package/dist/SwiperEmptyDataBug.lynx.bundle +0 -0
  61. package/dist/SwiperEmptyDataBug.web.bundle +1 -1
  62. package/package.json +4 -2
@@ -0,0 +1,41 @@
1
+ @import "@lynx-js/luna-styles/index.css";
2
+
3
+ .button {
4
+ height: 48px;
5
+ display: flex;
6
+ border-radius: 9999px;
7
+ justify-content: center;
8
+ align-items: center;
9
+ background-color: var(--neutral-ambient);
10
+ transition: opacity 0.15s ease-in-out;
11
+ }
12
+
13
+ .button.ui-active {
14
+ opacity: 0.5;
15
+ }
16
+
17
+ .button .text {
18
+ color: var(--content);
19
+ }
20
+
21
+ .button.primary {
22
+ background-color: var(--primary);
23
+ }
24
+
25
+ .button.primary .text {
26
+ color: var(--primary-content);
27
+ }
28
+
29
+ .text {
30
+ font-size: 15px;
31
+ line-height: 18px;
32
+ text-align: center;
33
+ font-weight: 600;
34
+ }
35
+
36
+ .sub-text {
37
+ font-size: 11px;
38
+ line-height: 14px;
39
+ text-align: center;
40
+ color: var(--content-muted);
41
+ }
@@ -0,0 +1,21 @@
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 {} from '@lynx-js/react'
6
+ import type { CSSProperties } from '@lynx-js/types'
7
+ import './styles.css'
8
+
9
+ export function Card({
10
+ index,
11
+ style,
12
+ }: {
13
+ index: number
14
+ style?: CSSProperties
15
+ }) {
16
+ return (
17
+ <view className='card' style={style}>
18
+ <text className='card-text'>{index}</text>
19
+ </view>
20
+ )
21
+ }
@@ -0,0 +1,21 @@
1
+ @import "@lynx-js/luna-styles/index.css";
2
+
3
+ .card {
4
+ width: 100%;
5
+ height: 100%;
6
+ display: flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ background-color: var(--canvas);
10
+
11
+ border-radius: 8px;
12
+ box-shadow:
13
+ 0 10px 15px -3px rgba(0, 0, 0, 0.1),
14
+ 0 4px 6px -4px rgba(0, 0, 0, 0.1);
15
+ }
16
+
17
+ .card-text {
18
+ color: var(--primary);
19
+ font-size: 64px;
20
+ font-weight: 600;
21
+ }
@@ -0,0 +1,24 @@
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 './styles.css'
6
+
7
+ export function Indicator({
8
+ current,
9
+ count,
10
+ }: {
11
+ current: number
12
+ count: number
13
+ }) {
14
+ return (
15
+ <view class='indicator-container'>
16
+ {Array.from({ length: count }).map((_, index) => (
17
+ <view
18
+ key={index}
19
+ class={`indicator-item ${index === current ? 'active' : ''}`}
20
+ />
21
+ ))}
22
+ </view>
23
+ )
24
+ }
@@ -0,0 +1,21 @@
1
+ @import "@lynx-js/luna-styles/index.css";
2
+
3
+ .indicator-container {
4
+ display: flex;
5
+ flex-direction: row;
6
+ align-items: center;
7
+ justify-content: center;
8
+ height: 48px;
9
+ }
10
+
11
+ .indicator-item {
12
+ width: 8px;
13
+ height: 8px;
14
+ border-radius: 50%;
15
+ background: var(--primary-content-faded);
16
+ margin: 4px;
17
+ }
18
+
19
+ .indicator-item.active {
20
+ background: var(--primary-content);
21
+ }
@@ -0,0 +1,87 @@
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, useRef } from '@lynx-js/react'
6
+
7
+ import {
8
+ Swiper,
9
+ SwiperItem,
10
+ interpolate,
11
+ interpolateJS,
12
+ } from '@lynx-js/lynx-ui'
13
+ import type { SwiperRef } from '@lynx-js/lynx-ui'
14
+
15
+ import './styles.css'
16
+
17
+ const colorsArr: string[] = ['red', 'green', 'yellow', 'purple']
18
+
19
+ function customAnimation(value: number, _index: number) {
20
+ 'main thread'
21
+
22
+ const scale = interpolate(value, [-1, 0, 1], [0.5, 1, 0.5])
23
+
24
+ return {
25
+ transform: `scale(${scale})`,
26
+ }
27
+ }
28
+
29
+ function customAnimationFirstScreen(value: number, _index: number) {
30
+ const scale = interpolateJS(value, [-1, 0, 1], [0.5, 1, 0.5])
31
+
32
+ return {
33
+ transform: `scale(${scale})`,
34
+ }
35
+ }
36
+
37
+ function SwiperEntry(): JSX.Element {
38
+ const swiperRef = useRef<SwiperRef>(null)
39
+
40
+ return (
41
+ <view id='container'>
42
+ <Swiper
43
+ ref={swiperRef}
44
+ data={colorsArr}
45
+ itemWidth={250}
46
+ duration={500}
47
+ initialIndex={0}
48
+ mode='normal'
49
+ modeConfig={{
50
+ align: 'center',
51
+ }}
52
+ main-thread:customAnimation={customAnimation}
53
+ customAnimationFirstScreen={customAnimationFirstScreen}
54
+ >
55
+ {({ item, index, realIndex }) => (
56
+ <SwiperItem index={index} key={realIndex} realIndex={realIndex}>
57
+ <view
58
+ class='block-view'
59
+ style={{
60
+ width: '100%',
61
+ height: '250px',
62
+ backgroundColor: item,
63
+ display: 'flex',
64
+ justifyContent: 'center',
65
+ alignItems: 'center',
66
+ }}
67
+ >
68
+ <view
69
+ style={{
70
+ backgroundColor: 'white',
71
+ width: '4px',
72
+ height: '4px',
73
+ }}
74
+ >
75
+ </view>
76
+ </view>
77
+ <text class='image-text'>Number.{index}</text>
78
+ </SwiperItem>
79
+ )}
80
+ </Swiper>
81
+ </view>
82
+ )
83
+ }
84
+
85
+ root.render(<SwiperEntry />)
86
+
87
+ export default SwiperEntry
@@ -0,0 +1,47 @@
1
+ .image {
2
+ width: 100%;
3
+ height: 100%;
4
+ }
5
+
6
+ .image-text {
7
+ position: absolute;
8
+ }
9
+
10
+ .container {
11
+ width: 100%;
12
+ height: 100%;
13
+ }
14
+
15
+ .title-container {
16
+ margin-top: 10px;
17
+ margin-bottom: 5px;
18
+ }
19
+
20
+ .title-text {
21
+ font-size: 16px;
22
+ }
23
+
24
+ .button {
25
+ border: 1px solid;
26
+ border-radius: 4px;
27
+ width: 150px;
28
+ background-color: red;
29
+ margin: 4px 8px;
30
+ padding: 4px 8px;
31
+ }
32
+
33
+ .button-text {
34
+ color: white;
35
+ }
36
+
37
+ .operation {
38
+ display: flex;
39
+ align-items: center;
40
+ flex-wrap: wrap;
41
+ }
42
+
43
+ .block {
44
+ display: flex;
45
+ width: 100%;
46
+ margin: 10px;
47
+ }
@@ -0,0 +1,116 @@
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, useRef } from '@lynx-js/react'
6
+
7
+ import {
8
+ Swiper,
9
+ SwiperItem,
10
+ interpolate,
11
+ interpolateJS,
12
+ } from '@lynx-js/lynx-ui'
13
+ import type { SwiperRef } from '@lynx-js/lynx-ui'
14
+
15
+ import './styles.css'
16
+
17
+ const colorsArr: string[] = ['red', 'green', 'yellow', 'purple']
18
+
19
+ const ITEM_WIDTH = 250
20
+
21
+ function customAnimation(value: number, _index: number) {
22
+ 'main thread'
23
+
24
+ const scale = interpolate(value, [-1, 0, 1], [0.8, 1, 0.8])
25
+ // const scale = 1
26
+
27
+ const centerOffset = ((lynx.__globalProps.screenWidth
28
+ ?? SystemInfo.pixelWidth / SystemInfo.pixelRatio) - ITEM_WIDTH) / 2
29
+ const translateX = interpolate(value, [-1, 0, 1], [
30
+ -ITEM_WIDTH + centerOffset,
31
+ centerOffset,
32
+ ITEM_WIDTH + centerOffset,
33
+ ], 'extend')
34
+
35
+ return {
36
+ transform: `translateX(${translateX}px) scale(${scale})`,
37
+ 'transform-origin': 'center',
38
+ }
39
+ }
40
+
41
+ function customAnimationFirstScreen(value: number, _index: number) {
42
+ const scale = interpolateJS(value, [-1, 0, 1], [0.8, 1, 0.8])
43
+ // const scale = 1
44
+ const centerOffset = ((lynx.__globalProps.screenWidth
45
+ ?? SystemInfo.pixelWidth / SystemInfo.pixelRatio) - ITEM_WIDTH) / 2
46
+ const translateX = interpolateJS(value, [-1, 0, 1], [
47
+ -ITEM_WIDTH + centerOffset,
48
+ centerOffset,
49
+ ITEM_WIDTH + centerOffset,
50
+ ], 'extend')
51
+
52
+ console.log(
53
+ 'customAnimationFirstScreen',
54
+ value,
55
+ scale,
56
+ translateX,
57
+ centerOffset,
58
+ )
59
+ return {
60
+ transform: `translateX(${translateX}px) scale(${scale})`,
61
+ 'transform-origin': 'center',
62
+ }
63
+ }
64
+
65
+ function SwiperEntry(): JSX.Element {
66
+ const swiperRef = useRef<SwiperRef>(null)
67
+
68
+ return (
69
+ <view id='container'>
70
+ <Swiper
71
+ ref={swiperRef}
72
+ data={colorsArr}
73
+ itemWidth={ITEM_WIDTH}
74
+ itemHeight={200}
75
+ duration={500}
76
+ initialIndex={0}
77
+ mode='custom'
78
+ modeConfig={{
79
+ align: 'center',
80
+ }}
81
+ main-thread:customAnimation={customAnimation}
82
+ customAnimationFirstScreen={customAnimationFirstScreen}
83
+ >
84
+ {({ item, index, realIndex }) => (
85
+ <SwiperItem index={index} key={realIndex} realIndex={realIndex}>
86
+ <view
87
+ class='block-view'
88
+ style={{
89
+ width: '100%',
90
+ height: '100%',
91
+ backgroundColor: item,
92
+ display: 'flex',
93
+ justifyContent: 'center',
94
+ alignItems: 'center',
95
+ }}
96
+ >
97
+ <view
98
+ style={{
99
+ backgroundColor: 'white',
100
+ width: '4px',
101
+ height: '4px',
102
+ }}
103
+ >
104
+ </view>
105
+ </view>
106
+ <text class='image-text'>Number.{index}</text>
107
+ </SwiperItem>
108
+ )}
109
+ </Swiper>
110
+ </view>
111
+ )
112
+ }
113
+
114
+ root.render(<SwiperEntry />)
115
+
116
+ export default SwiperEntry
@@ -0,0 +1,41 @@
1
+ .image {
2
+ width: 100%;
3
+ height: 100%;
4
+ }
5
+
6
+ .image-text {
7
+ position: absolute;
8
+ }
9
+
10
+ .container {
11
+ width: 100%;
12
+ height: 100%;
13
+ }
14
+
15
+ .title-container {
16
+ margin-top: 10px;
17
+ margin-bottom: 5px;
18
+ }
19
+
20
+ .title-text {
21
+ font-size: 16px;
22
+ }
23
+
24
+ .button {
25
+ border: 1px solid;
26
+ border-radius: 4px;
27
+ width: 150px;
28
+ background-color: red;
29
+ margin: 4px 8px;
30
+ padding: 4px 8px;
31
+ }
32
+
33
+ .button-text {
34
+ color: white;
35
+ }
36
+
37
+ .operation {
38
+ display: flex;
39
+ align-items: center;
40
+ flex-wrap: wrap;
41
+ }
@@ -0,0 +1,24 @@
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 {} from '@lynx-js/react'
6
+ import './styles.css'
7
+
8
+ export function Card({
9
+ index,
10
+ }: {
11
+ index: number
12
+ }) {
13
+ return (
14
+ <view className='card'>
15
+ <text className='card-text'>{index}</text>
16
+ <text className='title'>
17
+ Swiper
18
+ </text>
19
+ <text className='subtitle'>
20
+ @lynx-js/lynx-ui
21
+ </text>
22
+ </view>
23
+ )
24
+ }
@@ -0,0 +1,111 @@
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 } from '@lynx-js/react'
6
+
7
+ import {
8
+ Swiper,
9
+ SwiperItem,
10
+ interpolate,
11
+ interpolateJS,
12
+ } from '@lynx-js/lynx-ui'
13
+
14
+ import { Card } from './Card'
15
+
16
+ import './styles.css'
17
+
18
+ const itemArr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
19
+ const ITEM_WIDTH = 220
20
+ const ITEM_HEIGHT = 330
21
+
22
+ const customAnimation = (value: number) => {
23
+ 'main thread'
24
+ const translateX = interpolate(value, [-1, 0], [-ITEM_WIDTH, 0], 'clamp')
25
+ const translateY = interpolate(value, [0, 1], [0, -18], 'extend')
26
+ const rotate = interpolate(value, [-1, 0], [-15, 0], 'clamp')
27
+ const scale = interpolate(value, [0, 1], [1, 0.95], 'extend')
28
+ const opacity = interpolate(value, [-1, -0.8, 0, 1], [0, 0.9, 1, 1], 'clamp')
29
+
30
+ return {
31
+ transform:
32
+ `translate(${translateX}px, ${translateY}px) rotateZ(${rotate}deg) scale(${scale})`,
33
+ opacity: opacity,
34
+ 'transform-origin': 'center',
35
+ }
36
+ }
37
+
38
+ const customAnimationFirstScreen = (value: number, _index: number) => {
39
+ const translateX = interpolateJS(value, [-1, 0], [-ITEM_WIDTH, 0], 'clamp')
40
+ const translateY = interpolateJS(value, [0, 1], [0, -18], 'extend')
41
+ const rotate = interpolateJS(value, [-1, 0], [-15, 0], 'clamp')
42
+ const zIndex = interpolateJS(
43
+ value,
44
+ itemArr.map((_, index) => index),
45
+ itemArr.map((_, index) => (itemArr.length - index) * 10),
46
+ 'extend',
47
+ )
48
+
49
+ const scale = interpolateJS(
50
+ value,
51
+ [0, 1, 0],
52
+ [1, 0.95, 1],
53
+ 'extend',
54
+ )
55
+ const opacity = interpolateJS(
56
+ value,
57
+ [-1, -0.8, 0, 1],
58
+ [0, 0.9, 1, 1],
59
+ 'clamp',
60
+ )
61
+
62
+ return {
63
+ transform:
64
+ `translate(${translateX}px, ${translateY}px) rotateZ(${rotate}deg) scale(${scale})`,
65
+ opacity: opacity,
66
+ 'transform-origin': 'center',
67
+ zIndex: zIndex,
68
+ }
69
+ }
70
+
71
+ function SwiperEntry() {
72
+ return (
73
+ <view className='demo-container lunaris-dark'>
74
+ <Swiper
75
+ data={itemArr}
76
+ itemWidth={ITEM_WIDTH}
77
+ itemHeight={ITEM_HEIGHT}
78
+ containerWidth={ITEM_WIDTH}
79
+ duration={500}
80
+ initialIndex={0}
81
+ mode='custom'
82
+ main-thread:customAnimation={customAnimation}
83
+ customAnimationFirstScreen={customAnimationFirstScreen}
84
+ style={{
85
+ overflow: 'visible',
86
+ }}
87
+ >
88
+ {({ index, realIndex }) => (
89
+ <SwiperItem index={index} key={realIndex} realIndex={realIndex}>
90
+ <view
91
+ class='block-view'
92
+ style={{
93
+ width: '100%',
94
+ height: '100%',
95
+ display: 'flex',
96
+ justifyContent: 'center',
97
+ alignItems: 'center',
98
+ }}
99
+ >
100
+ <Card index={index} />
101
+ </view>
102
+ </SwiperItem>
103
+ )}
104
+ </Swiper>
105
+ </view>
106
+ )
107
+ }
108
+
109
+ root.render(<SwiperEntry />)
110
+
111
+ export default SwiperEntry
@@ -0,0 +1,61 @@
1
+ @import "@lynx-js/luna-styles/index.css";
2
+
3
+ .demo-container {
4
+ display: flex;
5
+ width: 100%;
6
+ height: 100%;
7
+ flex-direction: column;
8
+ justify-content: center;
9
+ padding-top: 48px;
10
+ padding-bottom: 24px;
11
+ background: linear-gradient(
12
+ 0deg,
13
+ var(--gradient-a),
14
+ var(--gradient-b),
15
+ );
16
+ align-items: center;
17
+ }
18
+
19
+ .image {
20
+ width: 100%;
21
+ height: 100%;
22
+ }
23
+
24
+ .image-text {
25
+ position: absolute;
26
+ }
27
+
28
+ .card {
29
+ width: 100%;
30
+ height: 100%;
31
+ display: flex;
32
+ flex-direction: column;
33
+ align-items: center;
34
+ justify-content: center;
35
+ background-color: var(--canvas);
36
+ border-radius: 8px;
37
+ box-shadow:
38
+ 0 10px 15px -3px rgba(0, 0, 0, 0.1),
39
+ 0 4px 6px -4px rgba(0, 0, 0, 0.1);
40
+ border-color: var(--line);
41
+ border-width: 1px;
42
+ }
43
+
44
+ .card-text {
45
+ color: var(--primary);
46
+ font-size: 128px;
47
+ font-weight: 600;
48
+ }
49
+
50
+ .title {
51
+ font-size: 16px;
52
+ font-weight: 600;
53
+ color: var(--content);
54
+ margin-top: 4px;
55
+ }
56
+
57
+ .subtitle {
58
+ font-size: 10px;
59
+ color: var(--content-subtle);
60
+ margin-top: 1px;
61
+ }
@@ -0,0 +1,33 @@
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 './styles.css'
6
+ import { Button as ButtonInner } from '@lynx-js/lynx-ui'
7
+
8
+ const ButtonStyle = {
9
+ border: '1px solid',
10
+ 'border-radius': '4px',
11
+ width: '150px',
12
+ 'background-color': 'red',
13
+ margin: '4px 8px',
14
+ padding: '4px 8px',
15
+ }
16
+
17
+ const ButtonTextStyle = {
18
+ color: 'white',
19
+ }
20
+
21
+ export function Button(props: {
22
+ onClick: () => void
23
+ text: string
24
+ }) {
25
+ return (
26
+ <ButtonInner
27
+ style={ButtonStyle}
28
+ onClick={props.onClick}
29
+ >
30
+ <text style={ButtonTextStyle}>{props.text}</text>
31
+ </ButtonInner>
32
+ )
33
+ }