@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,320 @@
1
+ import React, {
2
+ CSSProperties,
3
+ forwardRef,
4
+ Ref,
5
+ useContext,
6
+ useEffect,
7
+ useImperativeHandle,
8
+ useMemo,
9
+ useRef,
10
+ useState,
11
+ } from 'react';
12
+ import { addCssKeyframes, cls, nextTick, removeCssStyleDom } from '@arco-design/mobile-utils';
13
+ import { TabCellUnderlineProps, TabCellUnderlineRef, UnderlineStyle } from './type';
14
+ import { getStyleWithVendor, useRefState, useSystem } from '../_helpers';
15
+ import { GlobalContext } from '../context-provider';
16
+
17
+ const TabCellUnderline = forwardRef(
18
+ (props: TabCellUnderlineProps, ref: Ref<TabCellUnderlineRef>) => {
19
+ const {
20
+ prefix,
21
+ useCaterpillar,
22
+ distance,
23
+ tabDirection,
24
+ underlineInnerStyle,
25
+ duration,
26
+ cellTrans,
27
+ showLine,
28
+ activeIndex,
29
+ wrapWidth,
30
+ wrapHeight,
31
+ jumpingDis,
32
+ translateZ,
33
+ caterpillarMaxScale,
34
+ caterpillarProperty,
35
+ underlineSize,
36
+ underlineThick,
37
+ underlineAdaptive,
38
+ renderUnderline,
39
+ getTabRect,
40
+ getTabCenterLeft,
41
+ } = props;
42
+ const { useRtl } = useContext(GlobalContext);
43
+ const [underlineStyle, setUnderlineStyle] = useState<UnderlineStyle>({});
44
+ const [caterpillar, caterpillarRef, setCaterpillar] = useRefState(false);
45
+ const [caterpillarDelay, setCaterpillarDelay] = useState(0);
46
+ const lineRef = useRef<HTMLDivElement | null>(null);
47
+ const timeRef = useRef(0);
48
+ const system = useSystem();
49
+ const isVertical = tabDirection === 'vertical';
50
+ const maxScaleWithDefault = caterpillarMaxScale || 2;
51
+ const translateZStr = translateZ ? ' translateZ(0)' : '';
52
+ const rtlRatio = isVertical && useRtl ? -1 : 1;
53
+
54
+ useImperativeHandle(
55
+ ref,
56
+ () => ({
57
+ setCaterpillarAnimate,
58
+ resetUnderlineStyle,
59
+ }),
60
+ [setCaterpillarAnimate, resetUnderlineStyle],
61
+ );
62
+
63
+ const animationKey = useMemo(() => {
64
+ if (!useCaterpillar) {
65
+ return '';
66
+ }
67
+ if (caterpillarProperty === 'size') {
68
+ return `tabsCaterpillar${isVertical ? 'W' : 'H'}${maxScaleWithDefault}`;
69
+ }
70
+ if (caterpillarMaxScale) {
71
+ return `tabsCaterpillar${isVertical ? 'X' : 'Y'}${caterpillarMaxScale}`;
72
+ }
73
+ return '';
74
+ }, [useCaterpillar, isVertical, caterpillarMaxScale, caterpillarProperty]);
75
+
76
+ useEffect(() => {
77
+ if (!animationKey) {
78
+ return;
79
+ }
80
+ const dir = isVertical ? 'X' : 'Y';
81
+ if (caterpillarProperty === 'size') {
82
+ const attr = isVertical ? 'width' : 'height';
83
+ addCssKeyframes(
84
+ animationKey,
85
+ `{
86
+ 0% {
87
+ ${attr}: 100%;
88
+ }
89
+ 50% {
90
+ ${attr}: ${100 * maxScaleWithDefault}%;
91
+ }
92
+ 100% {
93
+ ${attr}: 100%;
94
+ }
95
+ }`,
96
+ );
97
+ return;
98
+ }
99
+ addCssKeyframes(
100
+ animationKey,
101
+ `{
102
+ 0% {
103
+ transform: scale${dir}(1)${translateZStr};
104
+ -webkit-transform: scale${dir}(1)${translateZStr};
105
+ }
106
+ 50% {
107
+ transform: scale${dir}(${caterpillarMaxScale})${translateZStr};
108
+ -webkit-transform: scale${dir}(${caterpillarMaxScale})${translateZStr};
109
+ }
110
+ 100% {
111
+ transform: scale${dir}(1)${translateZStr};
112
+ -webkit-transform: scale${dir}(1)${translateZStr};
113
+ }
114
+ }`,
115
+ );
116
+ return () => {
117
+ removeCssStyleDom(animationKey);
118
+ };
119
+ }, [animationKey]);
120
+
121
+ useEffect(() => {
122
+ if (jumpingDis && useCaterpillar && system !== 'ios') {
123
+ const movedRatio = wrapWidth ? jumpingDis / wrapWidth : 0;
124
+ setCaterpillarAnimate(movedRatio);
125
+ }
126
+ }, [jumpingDis]);
127
+
128
+ useEffect(() => {
129
+ resetUnderlineStyle();
130
+ }, [
131
+ useCaterpillar,
132
+ caterpillar,
133
+ cellTrans,
134
+ duration,
135
+ tabDirection,
136
+ wrapWidth,
137
+ wrapHeight,
138
+ distance,
139
+ animationKey,
140
+ caterpillarDelay,
141
+ underlineSize,
142
+ underlineThick,
143
+ underlineAdaptive,
144
+ ]);
145
+
146
+ function getLineWidth(index: number) {
147
+ if (underlineAdaptive) {
148
+ return getTabRect(index).width;
149
+ }
150
+ const offsetSize = isVertical
151
+ ? lineRef.current?.offsetWidth
152
+ : lineRef.current?.offsetHeight;
153
+ const lineWidth = offsetSize || 0;
154
+ return lineWidth;
155
+ }
156
+
157
+ function getLineLeft(index: number) {
158
+ if (underlineAdaptive) {
159
+ return getTabRect(index).left;
160
+ }
161
+ const lineWidth = getLineWidth(index);
162
+ return getTabCenterLeft(index) - lineWidth / 2;
163
+ }
164
+
165
+ function getDescIndex() {
166
+ const comparedDis = distance * rtlRatio;
167
+ if (comparedDis > 0) {
168
+ return activeIndex - 1;
169
+ }
170
+ if (comparedDis < 0) {
171
+ return activeIndex + 1;
172
+ }
173
+ return activeIndex;
174
+ }
175
+
176
+ function getLineScale(ratio: number) {
177
+ const absRatio = Math.abs(ratio);
178
+ return absRatio > 0.5
179
+ ? (1 - absRatio) * 2 * (maxScaleWithDefault - 1) + 1
180
+ : absRatio * 2 * (maxScaleWithDefault - 1) + 1;
181
+ }
182
+
183
+ function getLineStyle(): UnderlineStyle {
184
+ if (!lineRef.current) {
185
+ return {};
186
+ }
187
+ const currentLeft = getLineLeft(activeIndex);
188
+ const descIndex = getDescIndex();
189
+ const descLeft = getLineLeft(descIndex);
190
+ const comparedDis = distance * rtlRatio;
191
+ const moveRatio = wrapWidth ? comparedDis / wrapWidth : 0;
192
+ const leftOffset = moveRatio * (currentLeft - descLeft);
193
+ const direc = isVertical ? 'X' : 'Y';
194
+ const transStyle: CSSProperties =
195
+ useCaterpillar && !jumpingDis && !underlineAdaptive
196
+ ? caterpillarProperty === 'size'
197
+ ? {
198
+ [isVertical ? 'width' : 'height']: `${
199
+ 100 * getLineScale(moveRatio)
200
+ }%`,
201
+ willChange: 'width',
202
+ }
203
+ : {
204
+ transform: `scale${direc}(${getLineScale(moveRatio)})`,
205
+ }
206
+ : {};
207
+ let adaptiveStyle: CSSProperties = {};
208
+ let adaptiveOuterStyle: CSSProperties = {};
209
+ if (underlineAdaptive) {
210
+ const currentWidth = getLineWidth(activeIndex);
211
+ const descWidth = getLineWidth(descIndex);
212
+ const widthOffset = moveRatio * (currentWidth - descWidth);
213
+ adaptiveStyle = {
214
+ [isVertical ? 'width' : 'height']:
215
+ comparedDis > 0 ? currentWidth - widthOffset : currentWidth + widthOffset,
216
+ willChange: 'width',
217
+ };
218
+ adaptiveOuterStyle = isVertical ? { width: 'auto' } : { height: 'auto' };
219
+ }
220
+ const outerSize = isVertical
221
+ ? {
222
+ width: underlineSize,
223
+ height: underlineThick,
224
+ }
225
+ : {
226
+ height: underlineSize,
227
+ width: underlineThick,
228
+ };
229
+ return {
230
+ outer: {
231
+ transform: `translate${direc}(${
232
+ comparedDis > 0 ? currentLeft - leftOffset : currentLeft + leftOffset
233
+ }px)${translateZStr}`,
234
+ ...outerSize,
235
+ ...adaptiveOuterStyle,
236
+ },
237
+ inner: {
238
+ ...transStyle,
239
+ ...adaptiveStyle,
240
+ },
241
+ };
242
+ }
243
+
244
+ function getUnderlineStyle(): UnderlineStyle {
245
+ const transStyle: CSSProperties = {};
246
+ if (!underlineAdaptive) {
247
+ if (useCaterpillar) {
248
+ transStyle.animationDuration = `${duration}ms`;
249
+ }
250
+ if (caterpillarRef.current && animationKey) {
251
+ transStyle.animationName = animationKey;
252
+ }
253
+ if (caterpillarDelay) {
254
+ transStyle.animationDelay = `-${caterpillarDelay}ms`;
255
+ }
256
+ }
257
+ const lineStyle: UnderlineStyle = getLineStyle();
258
+ return {
259
+ outer: getStyleWithVendor({
260
+ transitionDuration: cellTrans ? `${duration}ms` : '0ms',
261
+ ...(lineStyle.outer || {}),
262
+ }),
263
+ inner: getStyleWithVendor({
264
+ ...transStyle,
265
+ ...(lineStyle.inner || {}),
266
+ }),
267
+ };
268
+ }
269
+
270
+ function resetUnderlineStyle() {
271
+ setUnderlineStyle(getUnderlineStyle());
272
+ }
273
+
274
+ function setCaterpillarAnimate(movedRatio = 0) {
275
+ if (!duration) {
276
+ return;
277
+ }
278
+ const movedTime = (duration || 0) * Math.abs(movedRatio);
279
+ setCaterpillarDelay(movedTime);
280
+ nextTick(() => {
281
+ setCaterpillar(true);
282
+ });
283
+ if (timeRef.current) {
284
+ clearTimeout(timeRef.current);
285
+ }
286
+ timeRef.current = window.setTimeout(() => {
287
+ setCaterpillar(false);
288
+ setCaterpillarDelay(0);
289
+ }, (duration || 0) - movedTime + 20);
290
+ }
291
+
292
+ return renderUnderline ? (
293
+ <>{renderUnderline(underlineStyle, showLine, lineRef)}</>
294
+ ) : (
295
+ <div
296
+ className={cls(`${prefix}-underline`, { show: showLine })}
297
+ ref={lineRef}
298
+ style={underlineStyle.outer}
299
+ >
300
+ <div
301
+ className={cls(
302
+ `${prefix}-underline-inner`,
303
+ {
304
+ caterpillar,
305
+ 'custom-animate': animationKey,
306
+ 'caterpillar-moving': caterpillar || (useCaterpillar && distance),
307
+ },
308
+ tabDirection,
309
+ )}
310
+ style={{
311
+ ...(underlineStyle.inner || {}),
312
+ ...(underlineInnerStyle || {}),
313
+ }}
314
+ />
315
+ </div>
316
+ );
317
+ },
318
+ );
319
+
320
+ export default TabCellUnderline;