@fjyueke/arco-mcp 1.0.0

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 (191) hide show
  1. package/README.md +85 -0
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.js +244 -0
  4. package/metaData/components/action-sheet/doc.md +102 -0
  5. package/metaData/components/action-sheet/example/index.tsx +199 -0
  6. package/metaData/components/action-sheet/example/methods.tsx +6 -0
  7. package/metaData/components/avatar/doc.md +57 -0
  8. package/metaData/components/avatar/example/group.tsx +69 -0
  9. package/metaData/components/avatar/example/index.tsx +196 -0
  10. package/metaData/components/badge/doc.md +28 -0
  11. package/metaData/components/badge/example/index.tsx +128 -0
  12. package/metaData/components/button/doc.md +45 -0
  13. package/metaData/components/button/example/index.tsx +264 -0
  14. package/metaData/components/carousel/doc.md +89 -0
  15. package/metaData/components/carousel/example/index.tsx +1481 -0
  16. package/metaData/components/cell/doc.md +68 -0
  17. package/metaData/components/cell/example/arrow.tsx +13 -0
  18. package/metaData/components/cell/example/cell.tsx +71 -0
  19. package/metaData/components/cell/example/group.tsx +63 -0
  20. package/metaData/components/cell/example/index.tsx +19 -0
  21. package/metaData/components/checkbox/doc.md +91 -0
  22. package/metaData/components/checkbox/example/checkbox.tsx +158 -0
  23. package/metaData/components/checkbox/example/group.tsx +103 -0
  24. package/metaData/components/checkbox/example/index.tsx +25 -0
  25. package/metaData/components/circle-progress/doc.md +40 -0
  26. package/metaData/components/circle-progress/example/index.tsx +323 -0
  27. package/metaData/components/collapse/doc.md +74 -0
  28. package/metaData/components/collapse/example/collapse.tsx +183 -0
  29. package/metaData/components/collapse/example/group.tsx +136 -0
  30. package/metaData/components/collapse/example/index.tsx +16 -0
  31. package/metaData/components/collapse/example/utils.tsx +20 -0
  32. package/metaData/components/context-provider/doc.md +44 -0
  33. package/metaData/components/context-provider/example/index.tsx +208 -0
  34. package/metaData/components/count-down/doc.md +40 -0
  35. package/metaData/components/count-down/example/hooks.tsx +118 -0
  36. package/metaData/components/count-down/example/index.tsx +63 -0
  37. package/metaData/components/date-picker/doc.md +102 -0
  38. package/metaData/components/date-picker/example/index.tsx +545 -0
  39. package/metaData/components/dialog/doc.md +200 -0
  40. package/metaData/components/dialog/example/index.tsx +328 -0
  41. package/metaData/components/dialog/example/methods.tsx +56 -0
  42. package/metaData/components/divider/doc.md +25 -0
  43. package/metaData/components/divider/example/index.tsx +87 -0
  44. package/metaData/components/dropdown/doc.md +80 -0
  45. package/metaData/components/dropdown/example/dropdown.tsx +308 -0
  46. package/metaData/components/dropdown/example/index.tsx +19 -0
  47. package/metaData/components/dropdown/example/options.tsx +103 -0
  48. package/metaData/components/dropdown-menu/doc.md +91 -0
  49. package/metaData/components/dropdown-menu/example/dropdown-menu.tsx +270 -0
  50. package/metaData/components/dropdown-menu/example/index.tsx +16 -0
  51. package/metaData/components/ellipsis/doc.md +33 -0
  52. package/metaData/components/ellipsis/example/index.tsx +93 -0
  53. package/metaData/components/ellipsis/example/js-ellipsis.tsx +229 -0
  54. package/metaData/components/ellipsis/example/native-ellipsis.tsx +48 -0
  55. package/metaData/components/form/doc.md +90 -0
  56. package/metaData/components/form/example/form-item-context.tsx +8 -0
  57. package/metaData/components/form/example/form-item.tsx +378 -0
  58. package/metaData/components/form/example/index.tsx +87 -0
  59. package/metaData/components/form/example/linked-container.tsx +66 -0
  60. package/metaData/components/grid/doc.md +39 -0
  61. package/metaData/components/grid/example/index.tsx +252 -0
  62. package/metaData/components/icon/doc.md +15 -0
  63. package/metaData/components/icon/example/index.tsx +32 -0
  64. package/metaData/components/image/doc.md +62 -0
  65. package/metaData/components/image/example/index.tsx +528 -0
  66. package/metaData/components/image-picker/doc.md +116 -0
  67. package/metaData/components/image-picker/example/add-icon.tsx +14 -0
  68. package/metaData/components/image-picker/example/index.tsx +175 -0
  69. package/metaData/components/image-preview/doc.md +119 -0
  70. package/metaData/components/image-preview/example/index.tsx +1290 -0
  71. package/metaData/components/image-preview/example/methods.tsx +72 -0
  72. package/metaData/components/index-bar/doc.md +83 -0
  73. package/metaData/components/index-bar/example/group.tsx +93 -0
  74. package/metaData/components/index-bar/example/index.tsx +271 -0
  75. package/metaData/components/index-bar/example/side-bar.tsx +82 -0
  76. package/metaData/components/input/doc.md +60 -0
  77. package/metaData/components/input/example/hooks.tsx +259 -0
  78. package/metaData/components/input/example/index.tsx +134 -0
  79. package/metaData/components/input/example/props.tsx +183 -0
  80. package/metaData/components/keyboard/doc.md +73 -0
  81. package/metaData/components/keyboard/example/index.tsx +238 -0
  82. package/metaData/components/load-more/doc.md +48 -0
  83. package/metaData/components/load-more/example/index.tsx +395 -0
  84. package/metaData/components/loading/doc.md +34 -0
  85. package/metaData/components/loading/example/index.tsx +312 -0
  86. package/metaData/components/masking/doc.md +93 -0
  87. package/metaData/components/masking/example/index.tsx +410 -0
  88. package/metaData/components/masking/example/methods.tsx +88 -0
  89. package/metaData/components/nav-bar/doc.md +40 -0
  90. package/metaData/components/nav-bar/example/back-icon.tsx +28 -0
  91. package/metaData/components/nav-bar/example/index.tsx +305 -0
  92. package/metaData/components/notice-bar/doc.md +34 -0
  93. package/metaData/components/notice-bar/example/index.tsx +294 -0
  94. package/metaData/components/notify/doc.md +81 -0
  95. package/metaData/components/notify/example/index.tsx +171 -0
  96. package/metaData/components/notify/example/methods.tsx +83 -0
  97. package/metaData/components/pagination/doc.md +41 -0
  98. package/metaData/components/pagination/example/arrow.tsx +14 -0
  99. package/metaData/components/pagination/example/index.tsx +292 -0
  100. package/metaData/components/picker/doc.md +89 -0
  101. package/metaData/components/picker/example/index.tsx +217 -0
  102. package/metaData/components/picker-view/doc.md +57 -0
  103. package/metaData/components/picker-view/example/cascader.tsx +141 -0
  104. package/metaData/components/picker-view/example/index.tsx +297 -0
  105. package/metaData/components/picker-view/example/multi-picker.tsx +66 -0
  106. package/metaData/components/picker-view/example/picker-cell.tsx +416 -0
  107. package/metaData/components/popover/doc.md +144 -0
  108. package/metaData/components/popover/example/index.tsx +23 -0
  109. package/metaData/components/popover/example/menu.tsx +145 -0
  110. package/metaData/components/popover/example/popover-inner.tsx +147 -0
  111. package/metaData/components/popover/example/popover.tsx +268 -0
  112. package/metaData/components/popup/doc.md +101 -0
  113. package/metaData/components/popup/example/index.tsx +125 -0
  114. package/metaData/components/popup/example/methods.tsx +6 -0
  115. package/metaData/components/popup-swiper/doc.md +108 -0
  116. package/metaData/components/popup-swiper/example/index.tsx +332 -0
  117. package/metaData/components/popup-swiper/example/methods.tsx +6 -0
  118. package/metaData/components/portal/doc.md +14 -0
  119. package/metaData/components/portal/example/index.tsx +35 -0
  120. package/metaData/components/progress/doc.md +42 -0
  121. package/metaData/components/progress/example/index.tsx +256 -0
  122. package/metaData/components/pull-refresh/doc.md +37 -0
  123. package/metaData/components/pull-refresh/example/android-pull-refresh.tsx +260 -0
  124. package/metaData/components/pull-refresh/example/index.tsx +44 -0
  125. package/metaData/components/pull-refresh/example/ios-pull-refresh.tsx +216 -0
  126. package/metaData/components/radio/doc.md +89 -0
  127. package/metaData/components/radio/example/group.tsx +92 -0
  128. package/metaData/components/radio/example/index.tsx +25 -0
  129. package/metaData/components/radio/example/radio.tsx +22 -0
  130. package/metaData/components/rate/doc.md +33 -0
  131. package/metaData/components/rate/example/index.tsx +281 -0
  132. package/metaData/components/search-bar/doc.md +97 -0
  133. package/metaData/components/search-bar/example/association.tsx +89 -0
  134. package/metaData/components/search-bar/example/cancel-button.tsx +34 -0
  135. package/metaData/components/search-bar/example/highlight.tsx +66 -0
  136. package/metaData/components/search-bar/example/index.tsx +251 -0
  137. package/metaData/components/show-monitor/doc.md +34 -0
  138. package/metaData/components/show-monitor/example/index.tsx +646 -0
  139. package/metaData/components/skeleton/doc.md +101 -0
  140. package/metaData/components/skeleton/example/elements.tsx +290 -0
  141. package/metaData/components/skeleton/example/index.tsx +96 -0
  142. package/metaData/components/skeleton/example/skeleton-context.tsx +7 -0
  143. package/metaData/components/slider/doc.md +42 -0
  144. package/metaData/components/slider/example/index.tsx +326 -0
  145. package/metaData/components/slider/example/marks.tsx +50 -0
  146. package/metaData/components/slider/example/popover.tsx +38 -0
  147. package/metaData/components/slider/example/thumb.tsx +48 -0
  148. package/metaData/components/slider/example/useSliderIcon.tsx +38 -0
  149. package/metaData/components/slider/example/useSliderInit.tsx +170 -0
  150. package/metaData/components/stepper/doc.md +46 -0
  151. package/metaData/components/stepper/example/index.tsx +166 -0
  152. package/metaData/components/stepper/example/useButtonClick.tsx +74 -0
  153. package/metaData/components/stepper/example/useInputEvent.tsx +65 -0
  154. package/metaData/components/stepper/example/useValue.tsx +43 -0
  155. package/metaData/components/steps/doc.md +57 -0
  156. package/metaData/components/steps/example/index.tsx +123 -0
  157. package/metaData/components/steps/example/step.tsx +126 -0
  158. package/metaData/components/sticky/doc.md +45 -0
  159. package/metaData/components/sticky/example/index.tsx +430 -0
  160. package/metaData/components/swipe-action/doc.md +44 -0
  161. package/metaData/components/swipe-action/example/index.tsx +338 -0
  162. package/metaData/components/swipe-action/example/item.tsx +40 -0
  163. package/metaData/components/swipe-load/doc.md +43 -0
  164. package/metaData/components/swipe-load/example/index.tsx +339 -0
  165. package/metaData/components/swipe-load/example/type.tsx +153 -0
  166. package/metaData/components/switch/doc.md +38 -0
  167. package/metaData/components/switch/example/index.tsx +237 -0
  168. package/metaData/components/tab-bar/doc.md +57 -0
  169. package/metaData/components/tab-bar/example/index.tsx +18 -0
  170. package/metaData/components/tab-bar/example/item.tsx +74 -0
  171. package/metaData/components/tab-bar/example/tab-bar.tsx +105 -0
  172. package/metaData/components/tabs/doc.md +187 -0
  173. package/metaData/components/tabs/example/index.tsx +514 -0
  174. package/metaData/components/tabs/example/tab-cell-underline.tsx +320 -0
  175. package/metaData/components/tabs/example/tab-cell.tsx +433 -0
  176. package/metaData/components/tabs/example/tab-pane.tsx +349 -0
  177. package/metaData/components/tag/doc.md +80 -0
  178. package/metaData/components/tag/example/index.tsx +23 -0
  179. package/metaData/components/tag/example/list.tsx +97 -0
  180. package/metaData/components/tag/example/tag.tsx +85 -0
  181. package/metaData/components/textarea/doc.md +67 -0
  182. package/metaData/components/textarea/example/index.tsx +258 -0
  183. package/metaData/components/toast/doc.md +90 -0
  184. package/metaData/components/toast/example/index.tsx +335 -0
  185. package/metaData/components/toast/example/methods.tsx +87 -0
  186. package/metaData/components/transition/doc.md +19 -0
  187. package/metaData/components/transition/example/index.tsx +113 -0
  188. package/metaData/components/uploader/doc.md +82 -0
  189. package/metaData/components/uploader/example/index.tsx +208 -0
  190. package/metaData/components-index.json +242 -0
  191. package/package.json +56 -0
@@ -0,0 +1,256 @@
1
+ import { cls } from '@arco-design/mobile-utils';
2
+ import React, { useRef, forwardRef, Ref, useImperativeHandle } from 'react';
3
+ import { ContextLayout } from '../context-provider';
4
+ import { getStyleWithVendor, useProgress } from '../_helpers';
5
+
6
+ type PercentPosition = 'left' | 'innerLeft' | 'right' | 'follow';
7
+ export type BezierType = [number, number, number, number];
8
+ export interface ProgressProps {
9
+ /**
10
+ * 自定义类名
11
+ * @en Custom classname
12
+ */
13
+ className?: string;
14
+ /**
15
+ * 自定义样式
16
+ * @en Custom stylesheet
17
+ */
18
+ style?: React.CSSProperties;
19
+ /**
20
+ * 文字显示位置
21
+ * @en Text display position
22
+ * @default "center"
23
+ */
24
+ percentPosition?: PercentPosition;
25
+ /**
26
+ * 是否显示进度条内部文字
27
+ * @en Whether to display the text inside the progress bar
28
+ * @default true
29
+ */
30
+ showPercent?: boolean;
31
+ /**
32
+ * 进度环百分比
33
+ * @en Progress percentage
34
+ */
35
+ percentage: number;
36
+ /**
37
+ * 进度条内部文字显示(一个函数,返回ReactNode类型,回调参数为当前进度百分比)
38
+ * @en The text display inside the progress bar (a function that returns the ReactNode type, and the callback parameter is the current progress percentage)
39
+ */
40
+ renderPercent?: (percentage: number) => React.ReactNode;
41
+ /**
42
+ * 轨道颜色
43
+ * @en Track color
44
+ */
45
+ trackColor?: string;
46
+ /**
47
+ * 进度条颜色
48
+ * @en Progress bar color
49
+ */
50
+ progressColor?: string;
51
+ /**
52
+ * 是否置灰
53
+ * @en Whether to be disabled
54
+ * @default false
55
+ */
56
+ disabled?: boolean;
57
+ /**
58
+ * 轨道粗细
59
+ * @en Track thickness
60
+ * @default 一般默认为4,percentPosition=innerLeft 时为18,mode=nav时为2
61
+ * @default_en Generally the default is 4, when percentPosition=innerLeft is 18, when mode=nav is 2
62
+ */
63
+ trackStroke?: number;
64
+ /**
65
+ * 进度条粗细
66
+ * @en progress bar thickness
67
+ * @default 继承 trackStroke 值
68
+ * @default_en Inherit trackStroke value
69
+ */
70
+ progressStroke?: number;
71
+ /**
72
+ * 每增加step步长所需的毫秒数
73
+ * @en The number of milliseconds required to increase the step size
74
+ * @default 300
75
+ */
76
+ duration?: number;
77
+ /**
78
+ * 步长(增加步长,以step增长)
79
+ * @en Step size (increase the step size, grow by step)
80
+ * @default 1
81
+ */
82
+ step?: number;
83
+ /**
84
+ * 进度条是否两端圆角
85
+ * @en Whether the progress bar has rounded corners at both ends
86
+ * @default true
87
+ */
88
+ filleted?: boolean;
89
+ /**
90
+ * 初始化percentage时是否以动画形式过渡到目的值
91
+ * @en Whether to animate the transition to the destination value when initializing percentage
92
+ * @default true
93
+ */
94
+ mountedTransition?: boolean;
95
+ /**
96
+ * 初始化时动画的贝塞尔曲线
97
+ * @en Animated bezier curves at initialization
98
+ * @default [0.34, 0.69, 0.1, 1]
99
+ */
100
+ mountedBezier?: BezierType;
101
+ /**
102
+ * 模式可选为nav或者base模式
103
+ * @en The mode can be selected as nav or base mode
104
+ * @default "base"
105
+ */
106
+ mode?: 'nav' | 'base';
107
+ /**
108
+ * 距离屏幕顶部的距离(只有当mode为"nav"才有效)
109
+ * @en The distance from the top of the screen (only valid when mode is "nav")
110
+ * @default 0
111
+ */
112
+ top?: number;
113
+ }
114
+
115
+ export interface ProgressRef {
116
+ /**
117
+ * 最外层元素 DOM
118
+ * @en The outermost element DOM
119
+ */
120
+ dom: HTMLDivElement | null;
121
+ }
122
+
123
+ /**
124
+ * 进度条组件,可根据外界传递进来的百分比进行进度展示
125
+ * @en Progress bar, which can display progress according to the percentage passed in from the outside
126
+ * @type 反馈
127
+ * @type_en Feedback
128
+ * @name 进度条
129
+ * @name_en Progress
130
+ */
131
+ const Progress = forwardRef((props: ProgressProps, ref: Ref<ProgressRef>) => {
132
+ const { mode = 'base' } = props;
133
+ const percentage = Math.min(100, Math.max(props.percentage, 0));
134
+ const {
135
+ top,
136
+ percentPosition = 'right',
137
+ className = '',
138
+ style,
139
+ showPercent = mode === 'base',
140
+ renderPercent,
141
+ trackColor,
142
+ progressColor,
143
+ disabled = false,
144
+ trackStroke,
145
+ progressStroke,
146
+ duration = 300,
147
+ step = 1,
148
+ filleted = true,
149
+ mountedTransition = true,
150
+ mountedBezier = [0.34, 0.69, 0.1, 1],
151
+ } = props;
152
+ const domRef = useRef<HTMLDivElement | null>(null);
153
+ const [currentPercentage, transitionControl] = useProgress(
154
+ mountedTransition,
155
+ percentage,
156
+ duration,
157
+ mountedBezier,
158
+ step,
159
+ );
160
+ useImperativeHandle(ref, () => ({
161
+ dom: domRef.current,
162
+ }));
163
+ function renderText(position?: PercentPosition) {
164
+ if (!showPercent) {
165
+ return null;
166
+ }
167
+ if (position === 'follow') {
168
+ return renderPercent !== void 0 ? (
169
+ renderPercent(currentPercentage)
170
+ ) : (
171
+ <div
172
+ className={cls('text-follow', {
173
+ 'inner-disabled inner-block-disabled': disabled,
174
+ })}
175
+ style={{ background: progressColor }}
176
+ >
177
+ {currentPercentage}%
178
+ </div>
179
+ );
180
+ }
181
+ if (position === percentPosition) {
182
+ return (
183
+ <div
184
+ style={{ color: progressColor }}
185
+ className={cls('text', `text-${percentPosition}`, {
186
+ 'text-disabled':
187
+ disabled && (percentPosition === 'left' || percentPosition === 'right'),
188
+ })}
189
+ >
190
+ {renderPercent !== void 0
191
+ ? renderPercent(currentPercentage)
192
+ : `${currentPercentage}%`}
193
+ </div>
194
+ );
195
+ }
196
+ return null;
197
+ }
198
+ function renderBarProgress({ prefixCls }) {
199
+ return (
200
+ <div
201
+ role="progressbar"
202
+ aria-valuenow={percentage}
203
+ aria-valuemax={100}
204
+ aria-valuemin={0}
205
+ className={cls(
206
+ `${prefixCls}-progress`,
207
+ { 'progress-fixed': mode === 'nav' },
208
+ { 'progress-disabled': disabled },
209
+ className,
210
+ )}
211
+ style={{
212
+ top,
213
+ ...style,
214
+ }}
215
+ ref={domRef}
216
+ >
217
+ <div className="progress-wrapper">
218
+ {renderText('left')}
219
+ <div
220
+ style={{
221
+ background: trackColor,
222
+ height: trackStroke,
223
+ }}
224
+ className={cls(
225
+ 'progress-track',
226
+ `position-${percentPosition}`,
227
+ { filleted },
228
+ { 'nav-mode': mode === 'nav' },
229
+ )}
230
+ >
231
+ <div
232
+ style={getStyleWithVendor({
233
+ background: progressColor,
234
+ width: `${currentPercentage}%`,
235
+ height: progressStroke,
236
+ transition: transitionControl
237
+ ? `width linear ${duration / 1000}s`
238
+ : '',
239
+ })}
240
+ className={cls('progress-bar', { 'bar-disabled': disabled, filleted })}
241
+ >
242
+ {percentPosition === 'follow' ? (
243
+ <div className="wrapper">{renderText('follow')}</div>
244
+ ) : null}
245
+ </div>
246
+ </div>
247
+ {renderText('right')}
248
+ {renderText('innerLeft')}
249
+ </div>
250
+ </div>
251
+ );
252
+ }
253
+ return <ContextLayout>{renderBarProgress}</ContextLayout>;
254
+ });
255
+
256
+ export default Progress;
@@ -0,0 +1,37 @@
1
+ ### 其他
2
+
3
+ # 下拉刷新 PullRefresh
4
+
5
+ 下拉刷新数据组件。
6
+
7
+ ======
8
+
9
+ > 属性/Props
10
+
11
+ |参数|描述|类型|默认值|
12
+ |----------|-------------|------|------|
13
+ |type|下拉刷新组件不同的实现方式,android \- 常规的外层容器 transform,ios \- 利用 ios scrollTop 负值实现下拉及回弹(性能优于transform),仅ios可用。指定该属性值后优先级高于 useIosOptimize|"ios" \| "android"|跟随系统|
14
+ |useIosOptimize|在 ios 上是否使用 scrollTop 负值实现下拉及回弹,而不是 transform,关闭后所有机型都使用 transform 的方式|boolean|false|
15
+ |children|子元素|ReactNode|必填|
16
+ |className|样式类名|string|-|
17
+ |style|自定义样式|CSSProperties|-|
18
+ |disabled|是否禁用|boolean|false|
19
+ |finishDelay|加载完成后,展示加载完成的时间(ms)|number|300|
20
+ |loosingText|下拉到可释放时的展示元素(type 为 ios 失效)|ReactNode|-|
21
+ |loadingText|加载中的展示元素|ReactNode|-|
22
+ |pullingText|下拉时的展示元素|ReactNode|-|
23
+ |finishText|加载完成的展示元素|ReactNode|-|
24
+ |initialText|初始状态还未下拉时的展示元素|ReactNode|pullingText属性值|
25
+ |dampRate|阻尼系数(type 为 ios 失效)|number|4|
26
+ |onRefresh|刷新触发事件|() =\> Promise\<void\>|-|
27
+ |useHideAsNestedScroll|惯性滑动时隐藏展示元素|boolean|true|
28
+ |loosingMinHeight|释放可刷线的最小距离(px)|number|loosingText 的高度|
29
+ |allowPullWhenNotTop|未滚到顶部时向下滑动也允许触发下拉刷新,可能影响ios回弹动画效果|boolean|false|
30
+
31
+ > 引用/Refs
32
+
33
+ |参数|描述|类型|
34
+ |----------|-------------|------|
35
+ |dom|最外层元素 DOM|HTMLDivElement|
36
+ |refresh|主动触发刷新,执行完成动画后异步返回|() =\> Promise\<void\>|
37
+ |updateIOSHeight|手动更新 IOS 容器自动高度|() =\> void|
@@ -0,0 +1,260 @@
1
+ import React, {
2
+ useRef,
3
+ forwardRef,
4
+ Ref,
5
+ useCallback,
6
+ useMemo,
7
+ useContext,
8
+ useEffect,
9
+ useImperativeHandle,
10
+ } from 'react';
11
+ import { cls, nextTick, defaultLocale } from '@arco-design/mobile-utils';
12
+ import { Promise } from 'es6-promise';
13
+ import Loading from '../loading';
14
+ import { GlobalContext } from '../context-provider';
15
+ import { PullRefreshRef, PullRefreshStatus, PullRefreshBasicProps } from './model';
16
+ import { useCommonState, useAddScrollEvents, useCheckAsStart } from './hooks';
17
+ import { setStyleWithVendor } from '../_helpers';
18
+
19
+ const dampRateCalculate = (val: number, tipsHeight: number, dampRate: number) =>
20
+ val > tipsHeight ? tipsHeight + (val - tipsHeight) / dampRate : val;
21
+
22
+ export const PullRefresh = forwardRef((props: PullRefreshBasicProps, ref: Ref<PullRefreshRef>) => {
23
+ const { prefixCls, locale = defaultLocale } = useContext(GlobalContext);
24
+
25
+ const {
26
+ className,
27
+ style,
28
+ children,
29
+ loosingText = (
30
+ <div className={cls(`${prefixCls}-pull-refresh-label-text`)}>
31
+ <span>{locale.PullRefresh.loosingText}</span>
32
+ </div>
33
+ ),
34
+ loadingText = (
35
+ <div className={cls(`${prefixCls}-pull-refresh-label-text`)}>
36
+ <Loading type="circle" radius={4} />
37
+ <span>{locale.PullRefresh.loadingText}</span>
38
+ </div>
39
+ ),
40
+ pullingText = (
41
+ <div className={cls(`${prefixCls}-pull-refresh-label-text`)}>
42
+ <span>{locale.PullRefresh.pullingText}</span>
43
+ </div>
44
+ ),
45
+ finishText = (
46
+ <div className={cls(`${prefixCls}-pull-refresh-label-text`)}>
47
+ <span>{locale.PullRefresh.finishText}</span>
48
+ </div>
49
+ ),
50
+ initialText,
51
+ finishDelay = 300,
52
+ loosingMinHeight,
53
+ dampRate = 4,
54
+ disabled = false,
55
+ useHideAsNestedScroll = true,
56
+ onRefresh,
57
+ allowPullWhenNotTop = false,
58
+ } = props;
59
+ const placeRef = useRef<HTMLDivElement>(null);
60
+ const touchRef = useRef<{ start: number; x: number; y: number } | null>(null);
61
+ const currentTranslateYRef = useRef(0);
62
+ const onTouching = useRef(false);
63
+ const {
64
+ loadingRef,
65
+ status,
66
+ setStatus,
67
+ labelRef,
68
+ domRef,
69
+ touching,
70
+ setTouching,
71
+ loosingHeight,
72
+ handleRefresh,
73
+ tipsHeight,
74
+ } = useCommonState({ loosingMinHeight, onRefresh });
75
+
76
+ const { ifShouldHandle } = useCheckAsStart({ domRef, allowPullWhenNotTop });
77
+
78
+ const currentLabelStyle = useMemo(() => {
79
+ return useHideAsNestedScroll &&
80
+ !touching &&
81
+ status === PullRefreshStatus.Pulling &&
82
+ (domRef?.current?.scrollTop ?? 0) > 0
83
+ ? { opacity: 0 }
84
+ : {};
85
+ }, [useHideAsNestedScroll, touching]);
86
+
87
+ const pullTextConfig = {
88
+ [PullRefreshStatus.Static]: initialText === void 0 ? pullingText : initialText,
89
+ [PullRefreshStatus.Pulling]: pullingText,
90
+ [PullRefreshStatus.Loosing]: loosingText || pullingText,
91
+ [PullRefreshStatus.Loading]: loadingText,
92
+ [PullRefreshStatus.Finish]: finishText,
93
+ };
94
+
95
+ const scroll = (y: number, ms: number, callback?: () => void) => {
96
+ if (y < 5) {
97
+ if (y < 0 || ms === 0) {
98
+ currentTranslateYRef.current = 0;
99
+ return;
100
+ }
101
+ }
102
+ const translateY = dampRateCalculate(y, loosingHeight, dampRate);
103
+ currentTranslateYRef.current = translateY;
104
+ placeRef.current &&
105
+ setStyleWithVendor(placeRef.current, {
106
+ transform: translateY ? `translateY(${translateY}px) translateZ(0)` : '',
107
+ ...(ms ? { transition: `all ${ms / 1000}s` } : {}),
108
+ });
109
+ callback &&
110
+ setTimeout(() => {
111
+ callback();
112
+ }, ms);
113
+ };
114
+
115
+ const reset = (callback = () => {}) => {
116
+ scroll(0, 300, () => {
117
+ if (domRef.current && domRef.current.scrollTop < 0) {
118
+ domRef.current.scrollTop = 0;
119
+ }
120
+ loadingRef.current = false;
121
+ setStatus(PullRefreshStatus.Static);
122
+ placeRef.current && setStyleWithVendor(placeRef.current, { transition: '' });
123
+ callback();
124
+ });
125
+ };
126
+
127
+ const handleTouchStart = useCallback(
128
+ (e: HTMLElementEventMap['touchstart']) => {
129
+ if (disabled || touchRef.current || loadingRef.current || !domRef.current) return;
130
+ if (!ifShouldHandle()) return;
131
+ setTouching(true);
132
+ const { pageX, pageY } = e.touches[0];
133
+ if (pageX && pageY) {
134
+ touchRef.current = { start: domRef.current?.scrollTop, x: pageX, y: pageY };
135
+ }
136
+ setStatus(PullRefreshStatus.Pulling);
137
+ },
138
+ [disabled, ifShouldHandle],
139
+ );
140
+
141
+ const refresh = () =>
142
+ new Promise<void>(resolve => {
143
+ setStatus(PullRefreshStatus.Loading);
144
+ nextTick(() => {
145
+ scroll(tipsHeight, 300);
146
+ handleRefresh().then(() => {
147
+ if (pullTextConfig[PullRefreshStatus.Finish]) {
148
+ setStatus(PullRefreshStatus.Finish);
149
+ setTimeout(() => {
150
+ reset(resolve);
151
+ }, finishDelay);
152
+ } else {
153
+ reset(resolve);
154
+ }
155
+ });
156
+ });
157
+ });
158
+ const handleTouchEnd = useCallback(() => {
159
+ if (currentTranslateYRef.current === 0 && !ifShouldHandle()) {
160
+ return;
161
+ }
162
+ onTouching.current = false;
163
+ setTouching(false);
164
+
165
+ if (disabled || !touchRef.current || loadingRef.current) return;
166
+ touchRef.current = null;
167
+ if (status === PullRefreshStatus.Loosing) {
168
+ refresh();
169
+ } else {
170
+ reset();
171
+ }
172
+ }, [disabled, status, tipsHeight, ifShouldHandle]);
173
+
174
+ const handleTouchMove = useCallback(
175
+ (e: HTMLElementEventMap['touchmove']) => {
176
+ onTouching.current = true;
177
+
178
+ if (disabled || loadingRef.current || !domRef.current) return;
179
+
180
+ if (!touchRef.current) return;
181
+ const { pageY } = e.touches[0];
182
+ const pullY = pageY - touchRef.current.y - touchRef.current.start;
183
+
184
+ if (currentTranslateYRef.current === 0 && domRef.current.scrollTop > 0) {
185
+ return;
186
+ }
187
+
188
+ if (currentTranslateYRef.current === 0 && pullY < 0) {
189
+ return;
190
+ }
191
+ setStatus(() =>
192
+ pullY > loosingHeight ? PullRefreshStatus.Loosing : PullRefreshStatus.Pulling,
193
+ );
194
+ scroll(pullY, 0);
195
+
196
+ e.stopPropagation();
197
+ e.cancelable && e.preventDefault();
198
+ },
199
+ [disabled, loosingHeight],
200
+ );
201
+
202
+ useEffect(() => {
203
+ const onScroll = () => {
204
+ if (
205
+ onTouching.current &&
206
+ domRef.current &&
207
+ (domRef.current.scrollTop < 0 || currentTranslateYRef.current)
208
+ ) {
209
+ // 禁止 ios 负 scrollTop 和双层滚动
210
+ domRef.current.scrollTop = 0;
211
+ }
212
+ };
213
+ domRef.current?.addEventListener('scroll', onScroll);
214
+ return () => {
215
+ domRef.current?.removeEventListener('scroll', onScroll);
216
+ };
217
+ }, []);
218
+
219
+ useImperativeHandle(ref, () => ({
220
+ dom: domRef.current,
221
+ refresh,
222
+ updateIOSHeight() {
223
+ console.warn('updateIOSHeight 仅在 type="ios" 时可用');
224
+ },
225
+ }));
226
+
227
+ useAddScrollEvents({ domRef, handleTouchStart, handleTouchMove, handleTouchEnd });
228
+
229
+ return (
230
+ <div
231
+ className={cls(`${prefixCls}-pull-refresh all-border-box is-android`, className, {
232
+ 'is-disabled':
233
+ (disabled || (!touching && useHideAsNestedScroll)) &&
234
+ status !== PullRefreshStatus.Loading,
235
+ })}
236
+ style={style}
237
+ ref={domRef}
238
+ >
239
+ <div className={cls(`${prefixCls}-pull-refresh-place`)} ref={placeRef}>
240
+ <div
241
+ className={cls(`${prefixCls}-pull-refresh-label`)}
242
+ ref={labelRef}
243
+ style={currentLabelStyle}
244
+ >
245
+ {pullTextConfig[status]}
246
+ </div>
247
+ <div
248
+ className={cls(`${prefixCls}-pull-refresh-content`, {
249
+ 'is-loading': [
250
+ PullRefreshStatus.Loading,
251
+ PullRefreshStatus.Finish,
252
+ ].includes(status),
253
+ })}
254
+ >
255
+ {children}
256
+ </div>
257
+ </div>
258
+ </div>
259
+ );
260
+ });
@@ -0,0 +1,44 @@
1
+ import React, { forwardRef, Ref } from 'react';
2
+ import { PullRefresh as IOSPullRefresh } from './ios-pull-refresh';
3
+ import { PullRefresh as AndroidPullRefresh } from './android-pull-refresh';
4
+ import { PullRefreshBasicProps, PullRefreshRef } from './model';
5
+ import { useSystem } from '../_helpers';
6
+
7
+ export type { PullRefreshRef } from './model';
8
+
9
+ export interface PullRefreshProps extends PullRefreshBasicProps {
10
+ /**
11
+ * 下拉刷新组件不同的实现方式,android - 常规的外层容器 transform,ios - 利用 ios scrollTop 负值实现下拉及回弹(性能优于transform),仅ios可用。指定该属性值后优先级高于 useIosOptimize
12
+ * @en Different implementation methods of PullRefresh, android - conventional outer container transform, ios - use ios scrollTop negative value to achieve pull-down and rebound (performance is better than transform), only available for ios. After specifying value, the priority is higher than useIosOptimize
13
+ * @default 跟随系统
14
+ * @default_en Follow the system
15
+ */
16
+ type?: 'ios' | 'android';
17
+ /**
18
+ * 在 ios 上是否使用 scrollTop 负值实现下拉及回弹,而不是 transform,关闭后所有机型都使用 transform 的方式
19
+ * @en Whether to use the negative value of scrollTop on ios to achieve pull-down and rebound instead of transform. After closing, all models use transform
20
+ * @default false
21
+ */
22
+ useIosOptimize?: boolean;
23
+ }
24
+
25
+ /**
26
+ * 下拉刷新数据组件。
27
+ * @en PullRefresh component that pulls down to refresh data.
28
+ * @name 下拉刷新
29
+ * @name_en PullRefresh
30
+ * @type 其他
31
+ * @type_en Others
32
+ */
33
+ const PullRefresh = forwardRef((props: PullRefreshProps, ref: Ref<PullRefreshRef>) => {
34
+ const { type, useIosOptimize, children, ...rest } = props;
35
+ const system = useSystem();
36
+
37
+ const Container =
38
+ type === 'ios' || (useIosOptimize && (type || system) === 'ios')
39
+ ? IOSPullRefresh
40
+ : AndroidPullRefresh;
41
+ return <Container {...{ ...rest, ref }}>{children}</Container>;
42
+ });
43
+
44
+ export default PullRefresh;