@ray-js/components 1.7.56-beta.5 → 1.7.56-beta.7
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/lib/Animated/index.d.ts +0 -7
- package/lib/Animated/index.js +153 -51
- package/lib/Animated/native/ty-animated/index.js +78 -35
- package/lib/Animated/native/ty-animated/index.tyml +7 -3
- package/lib/Animated/types.d.ts +46 -23
- package/lib/Animated-old/animation.d.ts +47 -0
- package/lib/Animated-old/index.d.ts +21 -0
- package/lib/Animated-old/index.js +359 -0
- package/lib/Animated-old/native/ty-animated/index.d.ts +5 -0
- package/lib/Animated-old/native/ty-animated/index.js +208 -0
- package/lib/Animated-old/native/ty-animated/index.json +4 -0
- package/lib/Animated-old/native/ty-animated/index.tyml +26 -0
- package/lib/Animated-old/native/ty-animated/index.tyss +3 -0
- package/lib/Animated-old/types.d.ts +312 -0
- package/lib/Animated-old/types.js +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* 触摸事件处理器(只保留核心事件)
|
|
4
|
+
*
|
|
5
|
+
* 注:只提供最常用的三个事件(onClick, onTouchStart, onTouchEnd)
|
|
6
|
+
* 如需其他事件(如 onLongPress, onTouchMove 等),请在 Animated 的子元素上直接绑定
|
|
7
|
+
*/
|
|
8
|
+
export interface TouchEventHandler {
|
|
9
|
+
onClick?: (e: TouchEvent) => any;
|
|
10
|
+
onTouchStart?: (e: TouchEvent) => any;
|
|
11
|
+
onTouchEnd?: (e: TouchEvent) => any;
|
|
12
|
+
}
|
|
13
|
+
interface TargetType {
|
|
14
|
+
id: string;
|
|
15
|
+
offsetLeft: number;
|
|
16
|
+
offsetTop: number;
|
|
17
|
+
paths: any;
|
|
18
|
+
uid: any;
|
|
19
|
+
dataset: {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface EventType {
|
|
24
|
+
type: string;
|
|
25
|
+
target: TargetType;
|
|
26
|
+
currentTarget: TargetType;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
stopPropagation: () => void;
|
|
29
|
+
detail: any;
|
|
30
|
+
}
|
|
31
|
+
export type timing = 'linear' | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'step-start' | 'step-end';
|
|
32
|
+
export type TOptions = {
|
|
33
|
+
duration?: number;
|
|
34
|
+
timingFunction?: timing;
|
|
35
|
+
delay?: number;
|
|
36
|
+
transformOrigin?: string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* 元素边界信息
|
|
40
|
+
*/
|
|
41
|
+
export interface BoundingClientRect {
|
|
42
|
+
/** 元素的 ID */
|
|
43
|
+
id: string;
|
|
44
|
+
/** dataset 数据 */
|
|
45
|
+
dataset: Record<string, any>;
|
|
46
|
+
/** 左边界坐标 */
|
|
47
|
+
left: number;
|
|
48
|
+
/** 右边界坐标 */
|
|
49
|
+
right: number;
|
|
50
|
+
/** 上边界坐标 */
|
|
51
|
+
top: number;
|
|
52
|
+
/** 下边界坐标 */
|
|
53
|
+
bottom: number;
|
|
54
|
+
/** 元素宽度 */
|
|
55
|
+
width: number;
|
|
56
|
+
/** 元素高度 */
|
|
57
|
+
height: number;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 元素查询字段配置
|
|
61
|
+
*/
|
|
62
|
+
export interface NodeFields {
|
|
63
|
+
/** 是否返回节点 id */
|
|
64
|
+
id?: boolean;
|
|
65
|
+
/** 是否返回节点 dataset */
|
|
66
|
+
dataset?: boolean;
|
|
67
|
+
/** 是否返回节点布局位置(left right top bottom) */
|
|
68
|
+
rect?: boolean;
|
|
69
|
+
/** 是否返回节点尺寸(width height) */
|
|
70
|
+
size?: boolean;
|
|
71
|
+
/** 是否返回节点的 scrollLeft scrollTop */
|
|
72
|
+
scrollOffset?: boolean;
|
|
73
|
+
/** 指定属性名列表,返回节点对应属性名的当前属性值 */
|
|
74
|
+
properties?: string[];
|
|
75
|
+
/** 指定样式名列表,返回节点对应样式名的当前值 */
|
|
76
|
+
computedStyle?: string[];
|
|
77
|
+
/** 是否返回节点对应的 Node 实例 */
|
|
78
|
+
node?: boolean;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Animated.View 组件的 Ref 类型(不包含 setText)
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```tsx
|
|
85
|
+
* import { useRef } from 'react'
|
|
86
|
+
* import Animated, { type AnimatedViewRef } from '@/components/animated'
|
|
87
|
+
*
|
|
88
|
+
* const boxRef = useRef<AnimatedViewRef>(null)
|
|
89
|
+
* boxRef.current?.setStyle({ opacity: 0.5 })
|
|
90
|
+
* boxRef.current?.animate((anim) => {
|
|
91
|
+
* anim.translateX(100).step({ duration: 300 })
|
|
92
|
+
* })
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export interface AnimatedViewRef {
|
|
96
|
+
/**
|
|
97
|
+
* 直接设置样式(无动画)
|
|
98
|
+
*
|
|
99
|
+
* 优势:不受 React 重渲染影响,可以在动画过程中随时调用 setState
|
|
100
|
+
* 而不用担心样式被覆盖或闪烁问题
|
|
101
|
+
*
|
|
102
|
+
* 注意:
|
|
103
|
+
* - 会清除动画数据并设置样式
|
|
104
|
+
* - 如果动画正在执行,会中断动画
|
|
105
|
+
* - 返回 Promise,可以等待样式应用完成
|
|
106
|
+
*
|
|
107
|
+
* @param style - 样式对象或 CSS 字符串
|
|
108
|
+
* @param callback - 可选的回调函数,样式应用完成后调用
|
|
109
|
+
* @returns Promise<void> - 样式应用完成后 resolve
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```tsx
|
|
113
|
+
* // 基本使用
|
|
114
|
+
* ref.current?.setStyle({ opacity: 0.5, color: 'red' })
|
|
115
|
+
*
|
|
116
|
+
* // 等待样式应用完成
|
|
117
|
+
* await ref.current?.setStyle({ opacity: 0 })
|
|
118
|
+
*
|
|
119
|
+
* // 如果需要获取 rect,单独调用
|
|
120
|
+
* await ref.current?.setStyle({ opacity: 0 })
|
|
121
|
+
* const rect = await ref.current?.getBoundingClientRect()
|
|
122
|
+
*
|
|
123
|
+
* // 使用回调
|
|
124
|
+
* ref.current?.setStyle({ color: 'red' }, () => {
|
|
125
|
+
* console.log('样式已应用')
|
|
126
|
+
* })
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
setStyle: (style: React.CSSProperties | string, callback?: () => void) => Promise<void>;
|
|
130
|
+
/**
|
|
131
|
+
* 创建动画对象
|
|
132
|
+
* 使用小程序原生动画 API,这是性能最优的动画方式
|
|
133
|
+
*
|
|
134
|
+
* @param options - 动画配置(可选)
|
|
135
|
+
* @param options.duration - 动画持续时间(毫秒),默认 400
|
|
136
|
+
* @param options.timingFunction - 缓动函数,默认 'linear'
|
|
137
|
+
* @param options.delay - 动画延迟时间(毫秒),默认 0
|
|
138
|
+
* @param options.transformOrigin - 变换原点,默认 '50% 50% 0'
|
|
139
|
+
* @returns Animation 实例,包含所有动画方法和 play() 方法
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```tsx
|
|
143
|
+
* // 基本使用
|
|
144
|
+
* const animation = ref.current.animate()
|
|
145
|
+
* animation.translateX(100).step({ duration: 300 })
|
|
146
|
+
* await animation.play()
|
|
147
|
+
* console.log('动画完成!')
|
|
148
|
+
*
|
|
149
|
+
* // 链式调用
|
|
150
|
+
* const animation = ref.current
|
|
151
|
+
* .animate({ transformOrigin: '50% 50%' })
|
|
152
|
+
* .translateX(100)
|
|
153
|
+
* .scale(1.2)
|
|
154
|
+
* .step({ duration: 300 })
|
|
155
|
+
* await animation.play()
|
|
156
|
+
*
|
|
157
|
+
* // 多段动画
|
|
158
|
+
* const animation = ref.current.animate()
|
|
159
|
+
* animation.translateX(100).step({ duration: 300 })
|
|
160
|
+
* animation.translateY(100).step({ duration: 300 })
|
|
161
|
+
* animation.scale(1.5).step({ duration: 300 })
|
|
162
|
+
* await animation.play()
|
|
163
|
+
*
|
|
164
|
+
* // 复用动画
|
|
165
|
+
* const slideIn = ref.current.animate().translateX(100).step({ duration: 300 })
|
|
166
|
+
* await slideIn.play() // 第一次
|
|
167
|
+
* await slideIn.play() // 第二次
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
animate: (options?: TOptions) => IAnimation & {
|
|
171
|
+
play(): Promise<void>;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* 获取元素的布局位置和尺寸信息
|
|
175
|
+
* 基于小程序 SelectorQuery.boundingClientRect API
|
|
176
|
+
*
|
|
177
|
+
* @returns Promise<BoundingClientRect | null>
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```tsx
|
|
181
|
+
* const rect = await boxRef.current?.getBoundingClientRect()
|
|
182
|
+
* console.log(rect?.left, rect?.top, rect?.width, rect?.height)
|
|
183
|
+
*
|
|
184
|
+
* // 使用位置信息实现动画
|
|
185
|
+
* if (rect) {
|
|
186
|
+
* const centerX = window.innerWidth / 2 - rect.left - rect.width / 2
|
|
187
|
+
* const centerY = window.innerHeight / 2 - rect.top - rect.height / 2
|
|
188
|
+
* boxRef.current?.animate((anim) => {
|
|
189
|
+
* anim.translateX(centerX).translateY(centerY).scale(2).step({ duration: 300 })
|
|
190
|
+
* })
|
|
191
|
+
* }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
getBoundingClientRect: () => Promise<BoundingClientRect | null>;
|
|
195
|
+
/**
|
|
196
|
+
* 获取元素的详细信息(包括样式、属性等)
|
|
197
|
+
* 基于小程序 SelectorQuery.fields API
|
|
198
|
+
*
|
|
199
|
+
* @param fields - 查询字段配置
|
|
200
|
+
* @returns Promise<any>
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```tsx
|
|
204
|
+
* // 获取元素的位置和计算后的样式
|
|
205
|
+
* const info = await boxRef.current?.getFields({
|
|
206
|
+
* rect: true,
|
|
207
|
+
* size: true,
|
|
208
|
+
* computedStyle: ['backgroundColor', 'transform']
|
|
209
|
+
* })
|
|
210
|
+
* console.log(info?.backgroundColor, info?.transform)
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
getFields: (fields: NodeFields) => Promise<any>;
|
|
214
|
+
/**
|
|
215
|
+
* 获取元素的计算后样式(computed style)
|
|
216
|
+
* 这是一个便捷方法,内部调用 getFields
|
|
217
|
+
*
|
|
218
|
+
* 使用注意事项:
|
|
219
|
+
* 1. width/height 限制:通过 CSS 自动布局的元素,width/height 通常返回 'auto'
|
|
220
|
+
* - 错误用法:用 getComputedStyle 获取实际像素尺寸
|
|
221
|
+
* - 正确用法:使用 getBoundingClientRect() 获取实际尺寸
|
|
222
|
+
*
|
|
223
|
+
* 2. 内联样式限制:通过 React style 属性设置的样式可能无法查询
|
|
224
|
+
* - 原因:小程序查询的是最终渲染的 CSS,不是 JS 设置的内联样式
|
|
225
|
+
*
|
|
226
|
+
* 3. 适用场景:
|
|
227
|
+
* - 查询 transform 动画状态(动画执行中)
|
|
228
|
+
* - 查询 opacity 等动画属性
|
|
229
|
+
* - 查询通过 CSS 类设置的样式
|
|
230
|
+
* - 查询元素实际尺寸(用 getBoundingClientRect)
|
|
231
|
+
* - 查询通过 style={{ }} 设置的背景色等
|
|
232
|
+
*
|
|
233
|
+
* @param styleNames - 样式名称数组
|
|
234
|
+
* @returns Promise<Record<string, any> | null> - 返回样式对象
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```tsx
|
|
238
|
+
* // 正确示例:查询动画相关样式
|
|
239
|
+
* const styles = await boxRef.current?.getComputedStyle([
|
|
240
|
+
* 'transform',
|
|
241
|
+
* 'opacity'
|
|
242
|
+
* ])
|
|
243
|
+
*
|
|
244
|
+
* console.log(styles?.transform) // 'matrix(1.5, 0, 0, 1.5, 100, 50)'
|
|
245
|
+
* console.log(styles?.opacity) // '0.8'
|
|
246
|
+
*
|
|
247
|
+
* // 根据当前 transform 决定下一步动画
|
|
248
|
+
* if (styles?.transform !== 'none') {
|
|
249
|
+
* // 当前有 transform,恢复原位
|
|
250
|
+
* boxRef.current?.animate((anim) => {
|
|
251
|
+
* anim.translateX(0).translateY(0).scale(1).step({ duration: 300 })
|
|
252
|
+
* })
|
|
253
|
+
* }
|
|
254
|
+
*
|
|
255
|
+
* // 错误示例:查询尺寸
|
|
256
|
+
* const styles = await boxRef.current?.getComputedStyle(['width', 'height'])
|
|
257
|
+
* console.log(styles?.width) // 可能返回 'auto',不是实际像素值
|
|
258
|
+
*
|
|
259
|
+
* // 正确做法:使用 getBoundingClientRect
|
|
260
|
+
* const rect = await boxRef.current?.getBoundingClientRect()
|
|
261
|
+
* console.log(rect?.width) // 335 (实际像素值)
|
|
262
|
+
* ```
|
|
263
|
+
*/
|
|
264
|
+
getComputedStyle: (styleNames: string[]) => Promise<Record<string, any> | null>;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Animated.Text 组件的 Ref 类型(包含 setText)
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```tsx
|
|
271
|
+
* import { useRef } from 'react'
|
|
272
|
+
* import Animated, { type AnimatedTextRef } from '@/components/animated'
|
|
273
|
+
*
|
|
274
|
+
* const textRef = useRef<AnimatedTextRef>(null)
|
|
275
|
+
* textRef.current?.setText('新文本')
|
|
276
|
+
* textRef.current?.animate((anim) => {
|
|
277
|
+
* anim.opacity(0.5).step({ duration: 300 })
|
|
278
|
+
* })
|
|
279
|
+
* ```
|
|
280
|
+
*/
|
|
281
|
+
export interface AnimatedTextRef extends AnimatedViewRef {
|
|
282
|
+
/**
|
|
283
|
+
* 直接设置文本内容(仅 Animated.Text 可用)
|
|
284
|
+
* 直接操作底层组件,不触发 React 重渲染
|
|
285
|
+
*
|
|
286
|
+
* @param text - 文本内容
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```tsx
|
|
290
|
+
* <Animated.Text ref={textRef}>0</Animated.Text>
|
|
291
|
+
* // 更新文本
|
|
292
|
+
* textRef.current?.setText('100')
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
setText: (text: string) => void;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Animated 组件 Props
|
|
299
|
+
*/
|
|
300
|
+
export interface AnimatedProps extends TouchEventHandler {
|
|
301
|
+
children?: React.ReactNode;
|
|
302
|
+
className?: string;
|
|
303
|
+
style?: React.CSSProperties;
|
|
304
|
+
id?: string;
|
|
305
|
+
/** 组件模式:'view' 为容器模式(默认),'text' 为文本模式 */
|
|
306
|
+
mode?: 'view' | 'text';
|
|
307
|
+
/** 动画开始回调 */
|
|
308
|
+
onAnimationStart?: () => void;
|
|
309
|
+
/** 动画结束回调 */
|
|
310
|
+
onAnimationEnd?: () => void;
|
|
311
|
+
}
|
|
312
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/lib/index.d.ts
CHANGED
|
@@ -33,5 +33,5 @@ export { default as Iframe } from './Iframe';
|
|
|
33
33
|
export { default as Modal } from './Modal';
|
|
34
34
|
export { default as Video } from './Video';
|
|
35
35
|
export { default as SvgRender } from './SvgRender';
|
|
36
|
-
export { default as Animated } from './Animated';
|
|
37
|
-
export type { AnimatedViewRef, AnimatedTextRef, AnimatedProps } from './Animated';
|
|
36
|
+
export { default as Animated } from './Animated ';
|
|
37
|
+
export type { AnimatedViewRef, AnimatedTextRef, AnimatedProps } from './Animated ';
|
package/lib/index.js
CHANGED
|
@@ -33,4 +33,4 @@ export { default as Iframe } from './Iframe';
|
|
|
33
33
|
export { default as Modal } from './Modal';
|
|
34
34
|
export { default as Video } from './Video';
|
|
35
35
|
export { default as SvgRender } from './SvgRender';
|
|
36
|
-
export { default as Animated } from './Animated';
|
|
36
|
+
export { default as Animated } from './Animated ';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ray-js/components",
|
|
3
|
-
"version": "1.7.56-beta.
|
|
3
|
+
"version": "1.7.56-beta.7",
|
|
4
4
|
"description": "Ray basic components",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ray"
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@ray-core/macro": "^0.4.9",
|
|
31
31
|
"@ray-core/wechat": "^0.4.9",
|
|
32
|
-
"@ray-js/adapter": "1.7.56-beta.
|
|
33
|
-
"@ray-js/framework-shared": "1.7.56-beta.
|
|
32
|
+
"@ray-js/adapter": "1.7.56-beta.7",
|
|
33
|
+
"@ray-js/framework-shared": "1.7.56-beta.7",
|
|
34
34
|
"ahooks": "^3.8.5",
|
|
35
35
|
"clsx": "^1.2.1",
|
|
36
36
|
"core-js": "^3.43.0",
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"style-to-object": "^0.3.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@ray-js/cli": "1.7.56-beta.
|
|
43
|
+
"@ray-js/cli": "1.7.56-beta.7"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public",
|
|
47
47
|
"registry": "https://registry.npmjs.org"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "4af5e87574c24597a6da1112bc3c40bf27df713c"
|
|
50
50
|
}
|