@vue-lynx-example/swiper 0.1.1

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 (47) hide show
  1. package/README.md +21 -0
  2. package/dist/static/image/1.282abf96.png +0 -0
  3. package/dist/static/image/2.e0b3d9f4.png +0 -0
  4. package/dist/static/image/3.3b83fa8b.png +0 -0
  5. package/dist/static/image/4.df45ef86.png +0 -0
  6. package/dist/static/image/5.719e0d42.png +0 -0
  7. package/dist/static/image/6.dbe87dd5.png +0 -0
  8. package/dist/static/image/7.66ac96a5.png +0 -0
  9. package/dist/static/image/8.93f167b4.png +0 -0
  10. package/dist/swiper-empty.lynx.bundle +0 -0
  11. package/dist/swiper-empty.web.bundle +1 -0
  12. package/dist/swiper-mts.lynx.bundle +0 -0
  13. package/dist/swiper-mts.web.bundle +1 -0
  14. package/dist/swiper.lynx.bundle +0 -0
  15. package/dist/swiper.web.bundle +1 -0
  16. package/lynx.config.ts +22 -0
  17. package/package.json +34 -0
  18. package/src/Components/Indicator.vue +21 -0
  19. package/src/Components/NavBar.vue +16 -0
  20. package/src/Components/Page.vue +32 -0
  21. package/src/Components/SafeArea.vue +10 -0
  22. package/src/Components/SwiperItem.vue +12 -0
  23. package/src/Swiper/Swiper.vue +63 -0
  24. package/src/Swiper/index.ts +23 -0
  25. package/src/Swiper/useOffset.ts +93 -0
  26. package/src/Swiper/useUpdateSwiperStyle.ts +21 -0
  27. package/src/SwiperEmpty/Swiper.vue +25 -0
  28. package/src/SwiperEmpty/index.ts +17 -0
  29. package/src/SwiperMTS/Swiper.vue +64 -0
  30. package/src/SwiperMTS/index.ts +17 -0
  31. package/src/assets/1.png +0 -0
  32. package/src/assets/2.png +0 -0
  33. package/src/assets/3.png +0 -0
  34. package/src/assets/4.png +0 -0
  35. package/src/assets/5.png +0 -0
  36. package/src/assets/6.png +0 -0
  37. package/src/assets/7.png +0 -0
  38. package/src/assets/8.png +0 -0
  39. package/src/assets/back.png +0 -0
  40. package/src/assets/heart.png +0 -0
  41. package/src/assets/star.png +0 -0
  42. package/src/shims-vue.d.ts +11 -0
  43. package/src/swiper.css +144 -0
  44. package/src/utils/const.ts +15 -0
  45. package/src/utils/pics.ts +21 -0
  46. package/src/utils/useAnimate.ts +106 -0
  47. package/tsconfig.json +10 -0
@@ -0,0 +1,64 @@
1
+ <script setup lang="ts">
2
+ import { useMainThreadRef } from 'vue-lynx';
3
+ import SwiperItem from '../Components/SwiperItem.vue';
4
+
5
+ declare const SystemInfo: { pixelWidth: number; pixelRatio: number };
6
+
7
+ const props = withDefaults(defineProps<{
8
+ data: string[];
9
+ itemWidth?: number;
10
+ }>(), {
11
+ itemWidth: () => SystemInfo.pixelWidth / SystemInfo.pixelRatio,
12
+ });
13
+
14
+ // --- Main Thread refs ---
15
+ const containerRef = useMainThreadRef<unknown>(null);
16
+ const currentOffsetRef = useMainThreadRef<number>(0);
17
+ const touchStartXRef = useMainThreadRef<number>(0);
18
+ const touchStartOffsetRef = useMainThreadRef<number>(0);
19
+
20
+ // --- MTS touch handlers ---
21
+ const handleTouchStart = (e: { touches: Array<{ clientX: number }> }) => {
22
+ 'main thread';
23
+ touchStartXRef.current = e.touches[0].clientX;
24
+ touchStartOffsetRef.current = currentOffsetRef.current;
25
+ };
26
+
27
+ const handleTouchMove = (e: { touches: Array<{ clientX: number }> }) => {
28
+ 'main thread';
29
+ const delta = e.touches[0].clientX - touchStartXRef.current;
30
+ const offset = touchStartOffsetRef.current + delta;
31
+ currentOffsetRef.current = offset;
32
+ const el = containerRef as unknown as {
33
+ current?: { setStyleProperty?(k: string, v: string): void };
34
+ };
35
+ if (el.current?.setStyleProperty) {
36
+ el.current.setStyleProperty('transform', `translateX(${offset}px)`);
37
+ }
38
+ };
39
+
40
+ const handleTouchEnd = () => {
41
+ 'main thread';
42
+ touchStartXRef.current = 0;
43
+ touchStartOffsetRef.current = 0;
44
+ };
45
+ </script>
46
+
47
+ <template>
48
+ <view class="swiper-wrapper">
49
+ <view
50
+ class="swiper-container"
51
+ :main-thread-ref="containerRef"
52
+ :main-thread-bindtouchstart="handleTouchStart"
53
+ :main-thread-bindtouchmove="handleTouchMove"
54
+ :main-thread-bindtouchend="handleTouchEnd"
55
+ >
56
+ <SwiperItem
57
+ v-for="(pic, index) in data"
58
+ :key="index"
59
+ :pic="pic"
60
+ :item-width="props.itemWidth"
61
+ />
62
+ </view>
63
+ </view>
64
+ </template>
@@ -0,0 +1,17 @@
1
+ import { createApp, defineComponent, h } from 'vue-lynx';
2
+
3
+ import '../swiper.css';
4
+ import Swiper from './Swiper.vue';
5
+ import Page from '../Components/Page.vue';
6
+ import { picsArr } from '../utils/pics.js';
7
+
8
+ const App = defineComponent({
9
+ setup() {
10
+ return () =>
11
+ h(Page, null, {
12
+ default: () => h(Swiper, { data: picsArr }),
13
+ });
14
+ },
15
+ });
16
+
17
+ createApp(App).mount();
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,11 @@
1
+ declare module '*.vue' {
2
+ import type { Component } from 'vue-lynx';
3
+
4
+ const component: Component;
5
+ export default component;
6
+ }
7
+
8
+ declare module '*.png' {
9
+ const src: string;
10
+ export default src;
11
+ }
package/src/swiper.css ADDED
@@ -0,0 +1,144 @@
1
+ /* Safe Area */
2
+ .safe-area {
3
+ width: 100%;
4
+ height: 100%;
5
+ padding-bottom: 20px;
6
+ display: flex;
7
+ flex-direction: column;
8
+ background-color: #000;
9
+ }
10
+ .safe-area.android {
11
+ padding-bottom: 0;
12
+ }
13
+
14
+ /* NavBar */
15
+ .nav-bar {
16
+ width: 100%;
17
+ height: 48px;
18
+ display: flex;
19
+ align-items: center;
20
+ position: relative;
21
+ justify-content: space-between;
22
+ background: black;
23
+ }
24
+ .nav-bar .left-icon {
25
+ width: 24px;
26
+ height: 24px;
27
+ margin-left: 20px;
28
+ }
29
+ .nav-bar .right-icon {
30
+ width: 24px;
31
+ height: 24px;
32
+ margin-right: 27px;
33
+ }
34
+ .nav-bar .nav-title {
35
+ position: absolute;
36
+ width: 100%;
37
+ text-align: center;
38
+ font-size: 20px;
39
+ font-weight: 500;
40
+ color: white;
41
+ }
42
+
43
+ /* Page */
44
+ .page-container {
45
+ flex: 1;
46
+ width: 100%;
47
+ padding-bottom: 30px;
48
+ display: flex;
49
+ flex-direction: column;
50
+ align-items: center;
51
+ background-color: #000;
52
+ }
53
+ .card-detail-container {
54
+ position: absolute;
55
+ width: 100%;
56
+ background: linear-gradient(
57
+ 180deg,
58
+ rgba(17, 17, 19, 0.00) 29.47%,
59
+ #111113 99.97%
60
+ );
61
+ bottom: 75px;
62
+ }
63
+ .card-detail {
64
+ background-color: #282e38;
65
+ border-radius: 12px;
66
+ width: calc(100% - 40px);
67
+ margin: 0 20px 18px 20px;
68
+ padding: 21px;
69
+ }
70
+ .card-detail-title {
71
+ display: flex;
72
+ justify-content: space-between;
73
+ align-items: center;
74
+ margin-bottom: 15px;
75
+ }
76
+ .card-detail-title-price {
77
+ font-size: 24px;
78
+ color: #ff6740;
79
+ }
80
+ .card-detail-amount {
81
+ color: rgba(255, 255, 255, 0.85);
82
+ text-align: right;
83
+ font-size: 12px;
84
+ }
85
+ .card-detail-desc {
86
+ display: flex;
87
+ justify-content: space-between;
88
+ align-items: center;
89
+ }
90
+ .card-detail-desc-text {
91
+ font-size: 17px;
92
+ color: rgba(255, 255, 255, 0.85);
93
+ }
94
+ .order-button {
95
+ background-color: #ff6740;
96
+ border-radius: 8px;
97
+ width: calc(100% - 40px);
98
+ margin: 0 20px;
99
+ padding: 13px 0;
100
+ display: flex;
101
+ justify-content: center;
102
+ align-items: center;
103
+ }
104
+ .order-text {
105
+ font-size: 17px;
106
+ color: #fff;
107
+ }
108
+
109
+ /* Indicator */
110
+ .indicator {
111
+ position: absolute;
112
+ bottom: 140px;
113
+ left: 50%;
114
+ transform: translateX(-50%);
115
+ display: flex;
116
+ justify-content: center;
117
+ align-items: center;
118
+ }
119
+ .indicator .indicator-item {
120
+ width: 10px;
121
+ height: 10px;
122
+ border-radius: 50%;
123
+ margin: 0 5px;
124
+ background-color: rgba(255, 255, 255, 0.5);
125
+ }
126
+ .indicator .indicator-item.active {
127
+ background-color: #ff6740;
128
+ }
129
+
130
+ /* Swiper */
131
+ .swiper-wrapper {
132
+ flex: 1;
133
+ width: 100%;
134
+ }
135
+ .swiper-container {
136
+ display: linear;
137
+ linear-orientation: horizontal;
138
+ height: 100%;
139
+ }
140
+ .swiper-item {
141
+ display: flex;
142
+ align-items: flex-end;
143
+ justify-content: center;
144
+ }
@@ -0,0 +1,15 @@
1
+ export const colorsArr = [
2
+ 'red',
3
+ 'green',
4
+ 'blue',
5
+ 'yellow',
6
+ 'purple',
7
+ 'orange',
8
+ 'pink',
9
+ 'brown',
10
+ 'gray',
11
+ 'black',
12
+ 'white',
13
+ ];
14
+
15
+ export const SWIPER_ITEM_WIDTH = 300;
@@ -0,0 +1,21 @@
1
+ import pic1 from '../assets/1.png';
2
+ import pic2 from '../assets/2.png';
3
+ import pic3 from '../assets/3.png';
4
+ import pic4 from '../assets/4.png';
5
+ import pic5 from '../assets/5.png';
6
+ import pic6 from '../assets/6.png';
7
+ import pic7 from '../assets/7.png';
8
+ import pic8 from '../assets/8.png';
9
+
10
+ export const pics = [
11
+ { src: pic1, width: 511, height: 437 },
12
+ { src: pic2, width: 1024, height: 1589 },
13
+ { src: pic3, width: 510, height: 418 },
14
+ { src: pic4, width: 509, height: 438 },
15
+ { src: pic5, width: 1024, height: 1557 },
16
+ { src: pic6, width: 509, height: 415 },
17
+ { src: pic7, width: 509, height: 426 },
18
+ { src: pic8, width: 1024, height: 1544 },
19
+ ];
20
+
21
+ export const picsArr = pics.slice(0, 8).map((pic) => pic.src);
@@ -0,0 +1,106 @@
1
+ import { useMainThreadRef } from 'vue-lynx';
2
+
3
+ export interface AnimationOptions {
4
+ from: number;
5
+ to: number;
6
+ duration?: number;
7
+ delay?: number;
8
+ easing?: (t: number) => number;
9
+ onUpdate?: (value: number) => void;
10
+ onComplete?: () => void;
11
+ }
12
+
13
+ // Common easing functions
14
+ export const easings = {
15
+ linear: (t: number) => {
16
+ 'main thread';
17
+ return t;
18
+ },
19
+ easeInQuad: (t: number) => {
20
+ 'main thread';
21
+ return t * t;
22
+ },
23
+ easeOutQuad: (t: number) => {
24
+ 'main thread';
25
+ return 1 - (1 - t) * (1 - t);
26
+ },
27
+ easeInOutQuad: (t: number) => {
28
+ 'main thread';
29
+ return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
30
+ },
31
+ };
32
+
33
+ function animateInner(options: AnimationOptions) {
34
+ 'main thread';
35
+ const {
36
+ from,
37
+ to,
38
+ duration = 5000,
39
+ delay = 0,
40
+ easing = easings.easeInOutQuad,
41
+ onUpdate,
42
+ onComplete,
43
+ } = options;
44
+
45
+ let startTs = 0;
46
+ let rafId = 0;
47
+
48
+ function tick(ts: number) {
49
+ const progress =
50
+ Math.max(Math.min(((ts - startTs - delay) * 100) / duration, 100), 0)
51
+ / 100;
52
+
53
+ const easedProgress = easing(progress);
54
+ const currentValue = from + (to - from) * easedProgress;
55
+ onUpdate?.(currentValue);
56
+ }
57
+
58
+ function updateRafId(id: number) {
59
+ rafId = id;
60
+ }
61
+
62
+ function step(ts: number) {
63
+ if (!startTs) {
64
+ startTs = Number(ts);
65
+ }
66
+ // make sure progress can reach 100%
67
+ if (ts - startTs <= duration + 100) {
68
+ tick(ts);
69
+ updateRafId(requestAnimationFrame(step));
70
+ } else {
71
+ onComplete?.();
72
+ }
73
+ }
74
+
75
+ updateRafId(requestAnimationFrame(step));
76
+
77
+ function cancel() {
78
+ cancelAnimationFrame(rafId);
79
+ }
80
+
81
+ return {
82
+ cancel,
83
+ };
84
+ }
85
+
86
+ export function useAnimate() {
87
+ const lastCancelRef = useMainThreadRef<(() => void) | null>(null);
88
+
89
+ function cancel() {
90
+ 'main thread';
91
+ lastCancelRef.current?.();
92
+ }
93
+
94
+ function animate(options: AnimationOptions) {
95
+ 'main thread';
96
+ cancel();
97
+
98
+ const { cancel: innerCancel } = animateInner(options);
99
+ lastCancelRef.current = innerCancel;
100
+ }
101
+
102
+ return {
103
+ cancel,
104
+ animate,
105
+ };
106
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": ".",
5
+ "noEmit": true,
6
+ "noUnusedLocals": false,
7
+ "noUnusedParameters": false,
8
+ },
9
+ "include": ["src", "lynx.config.ts"],
10
+ }