@xhsreds/reds-rn-next 0.11.1-premode-test.0 → 0.11.1-web202512221520

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 (172) hide show
  1. package/coverage/.tmp/coverage-10.json +1 -1
  2. package/coverage/.tmp/coverage-11.json +1 -1
  3. package/coverage/.tmp/coverage-12.json +1 -1
  4. package/coverage/.tmp/coverage-13.json +1 -1
  5. package/coverage/.tmp/coverage-14.json +1 -1
  6. package/coverage/.tmp/coverage-15.json +1 -1
  7. package/coverage/.tmp/coverage-16.json +1 -1
  8. package/coverage/.tmp/coverage-21.json +1 -1
  9. package/coverage/.tmp/coverage-22.json +1 -1
  10. package/coverage/.tmp/coverage-23.json +1 -1
  11. package/coverage/.tmp/coverage-3.json +1 -1
  12. package/coverage/.tmp/coverage-30.json +1 -1
  13. package/coverage/.tmp/coverage-31.json +1 -1
  14. package/coverage/.tmp/coverage-32.json +1 -1
  15. package/coverage/.tmp/coverage-33.json +1 -1
  16. package/coverage/.tmp/coverage-34.json +1 -1
  17. package/coverage/.tmp/coverage-35.json +1 -1
  18. package/coverage/.tmp/coverage-36.json +1 -1
  19. package/coverage/.tmp/coverage-37.json +1 -1
  20. package/coverage/.tmp/coverage-38.json +1 -1
  21. package/coverage/.tmp/coverage-39.json +1 -1
  22. package/coverage/.tmp/coverage-4.json +1 -1
  23. package/coverage/.tmp/coverage-40.json +1 -1
  24. package/coverage/.tmp/coverage-41.json +1 -1
  25. package/coverage/.tmp/coverage-5.json +1 -1
  26. package/coverage/.tmp/coverage-6.json +1 -1
  27. package/coverage/.tmp/coverage-7.json +1 -1
  28. package/coverage/.tmp/coverage-8.json +1 -1
  29. package/coverage/.tmp/coverage-9.json +1 -1
  30. package/lib/cjs/_chunks/BiKD1VTc.js.map +1 -1
  31. package/lib/cjs/components/ActionSheets/ActionSheets.js.map +1 -1
  32. package/lib/cjs/components/ActionablePopover/ActionablePopover.js +3 -0
  33. package/lib/cjs/components/ActionablePopover/ActionablePopover.js.map +1 -1
  34. package/lib/cjs/components/Alert/Alert.js +12 -9
  35. package/lib/cjs/components/Alert/Alert.js.map +1 -1
  36. package/lib/cjs/components/Alert/hooks/alert.js +1 -0
  37. package/lib/cjs/components/Alert/hooks/alert.js.map +1 -1
  38. package/lib/cjs/components/Alert/index.js +1 -0
  39. package/lib/cjs/components/Alert/index.js.map +1 -1
  40. package/lib/cjs/components/Button/Viewable.web.js +47 -0
  41. package/lib/cjs/components/Button/Viewable.web.js.map +1 -0
  42. package/lib/cjs/components/Collapse/Item/Item.web.js +164 -0
  43. package/lib/cjs/components/Collapse/Item/Item.web.js.map +1 -0
  44. package/lib/cjs/components/Image/index.js +1 -1
  45. package/lib/cjs/components/Image/index.js.map +1 -1
  46. package/lib/cjs/components/NoticeBar/NoticeBar.js +12 -6
  47. package/lib/cjs/components/NoticeBar/NoticeBar.js.map +1 -1
  48. package/lib/cjs/components/PickerView/PickerView.js +2 -1
  49. package/lib/cjs/components/PickerView/PickerView.js.map +1 -1
  50. package/lib/cjs/components/PickerView/Wheel.js +22 -2
  51. package/lib/cjs/components/PickerView/Wheel.js.map +1 -1
  52. package/lib/cjs/components/Popover/Popover.js +24 -28
  53. package/lib/cjs/components/Popover/Popover.js.map +1 -1
  54. package/lib/cjs/components/ProgressIndicator/ProgressIndicator.js +3 -3
  55. package/lib/cjs/components/ProgressIndicator/ProgressIndicator.js.map +1 -1
  56. package/lib/cjs/components/Radio/Radio.js +1 -0
  57. package/lib/cjs/components/Radio/Radio.js.map +1 -1
  58. package/lib/cjs/components/Radio/index.js +1 -0
  59. package/lib/cjs/components/Radio/index.js.map +1 -1
  60. package/lib/cjs/components/Sheets/AnimatedSheets.js +13 -2
  61. package/lib/cjs/components/Sheets/AnimatedSheets.js.map +1 -1
  62. package/lib/cjs/components/SlimAlert/Alert.js +12 -8
  63. package/lib/cjs/components/SlimAlert/Alert.js.map +1 -1
  64. package/lib/cjs/components/SlimAlert/PortalHost.js +28 -0
  65. package/lib/cjs/components/SlimAlert/PortalHost.js.map +1 -0
  66. package/lib/cjs/components/SlimAlert/PortalHost.web.js +12171 -0
  67. package/lib/cjs/components/SlimAlert/PortalHost.web.js.map +1 -0
  68. package/lib/cjs/components/SlimAlert/index.js +1 -0
  69. package/lib/cjs/components/SlimAlert/index.js.map +1 -1
  70. package/lib/cjs/components/Tag/Tag.js +10 -3
  71. package/lib/cjs/components/Tag/Tag.js.map +1 -1
  72. package/lib/cjs/components/TextField/TextField.js +22 -12
  73. package/lib/cjs/components/TextField/TextField.js.map +1 -1
  74. package/lib/cjs/components/TextView/TextView.js +4 -2
  75. package/lib/cjs/components/TextView/TextView.js.map +1 -1
  76. package/lib/cjs/components/Toast/Toast.js +1 -1
  77. package/lib/cjs/components/Toast/Toast.js.map +1 -1
  78. package/lib/cjs/index.js +1 -0
  79. package/lib/cjs/index.js.map +1 -1
  80. package/lib/cjs/pvCount/pvData.js +11 -6
  81. package/lib/cjs/pvCount/pvData.js.map +1 -1
  82. package/lib/esm/_chunks/Dr5vetot.js.map +1 -1
  83. package/lib/esm/components/ActionSheets/ActionSheets.js.map +1 -1
  84. package/lib/esm/components/ActionablePopover/ActionablePopover.js +3 -0
  85. package/lib/esm/components/ActionablePopover/ActionablePopover.js.map +1 -1
  86. package/lib/esm/components/Alert/Alert.js +12 -9
  87. package/lib/esm/components/Alert/Alert.js.map +1 -1
  88. package/lib/esm/components/Alert/hooks/alert.js +1 -0
  89. package/lib/esm/components/Alert/hooks/alert.js.map +1 -1
  90. package/lib/esm/components/Alert/index.js +1 -0
  91. package/lib/esm/components/Alert/index.js.map +1 -1
  92. package/lib/esm/components/Button/Viewable.web.js +43 -0
  93. package/lib/esm/components/Button/Viewable.web.js.map +1 -0
  94. package/lib/esm/components/Collapse/Item/Item.web.js +160 -0
  95. package/lib/esm/components/Collapse/Item/Item.web.js.map +1 -0
  96. package/lib/esm/components/Image/index.js +1 -1
  97. package/lib/esm/components/Image/index.js.map +1 -1
  98. package/lib/esm/components/NoticeBar/NoticeBar.js +13 -7
  99. package/lib/esm/components/NoticeBar/NoticeBar.js.map +1 -1
  100. package/lib/esm/components/PickerView/PickerView.js +2 -1
  101. package/lib/esm/components/PickerView/PickerView.js.map +1 -1
  102. package/lib/esm/components/PickerView/Wheel.js +23 -3
  103. package/lib/esm/components/PickerView/Wheel.js.map +1 -1
  104. package/lib/esm/components/Popover/Popover.js +24 -28
  105. package/lib/esm/components/Popover/Popover.js.map +1 -1
  106. package/lib/esm/components/ProgressIndicator/ProgressIndicator.js +4 -4
  107. package/lib/esm/components/ProgressIndicator/ProgressIndicator.js.map +1 -1
  108. package/lib/esm/components/Radio/Radio.js +1 -0
  109. package/lib/esm/components/Radio/Radio.js.map +1 -1
  110. package/lib/esm/components/Radio/index.js +1 -0
  111. package/lib/esm/components/Radio/index.js.map +1 -1
  112. package/lib/esm/components/Sheets/AnimatedSheets.js +13 -2
  113. package/lib/esm/components/Sheets/AnimatedSheets.js.map +1 -1
  114. package/lib/esm/components/SlimAlert/Alert.js +12 -8
  115. package/lib/esm/components/SlimAlert/Alert.js.map +1 -1
  116. package/lib/esm/components/SlimAlert/PortalHost.js +24 -0
  117. package/lib/esm/components/SlimAlert/PortalHost.js.map +1 -0
  118. package/lib/esm/components/SlimAlert/PortalHost.web.js +12167 -0
  119. package/lib/esm/components/SlimAlert/PortalHost.web.js.map +1 -0
  120. package/lib/esm/components/SlimAlert/index.js +1 -0
  121. package/lib/esm/components/SlimAlert/index.js.map +1 -1
  122. package/lib/esm/components/Tag/Tag.js +12 -5
  123. package/lib/esm/components/Tag/Tag.js.map +1 -1
  124. package/lib/esm/components/TextField/TextField.js +22 -12
  125. package/lib/esm/components/TextField/TextField.js.map +1 -1
  126. package/lib/esm/components/TextView/TextView.js +4 -2
  127. package/lib/esm/components/TextView/TextView.js.map +1 -1
  128. package/lib/esm/components/Toast/Toast.js +2 -2
  129. package/lib/esm/components/Toast/Toast.js.map +1 -1
  130. package/lib/esm/index.js +1 -0
  131. package/lib/esm/index.js.map +1 -1
  132. package/lib/esm/pvCount/pvData.js +11 -6
  133. package/lib/esm/pvCount/pvData.js.map +1 -1
  134. package/lib/src/components/Button/Viewable.web.d.ts +3 -0
  135. package/lib/src/components/Collapse/Item/Item.web.d.ts +7 -0
  136. package/lib/src/components/Form/interface/index.d.ts +0 -1
  137. package/lib/src/components/Image/interface/index.d.ts +0 -2
  138. package/lib/src/components/Search/interface/index.d.ts +0 -2
  139. package/lib/src/components/Slider/interface/index.d.ts +0 -2
  140. package/lib/src/components/SlimAlert/Alert.d.ts +1 -1
  141. package/lib/src/components/SlimAlert/PortalHost.d.ts +6 -0
  142. package/lib/src/components/SlimAlert/PortalHost.web.d.ts +6 -0
  143. package/lib/src/components/Video/interface/index.d.ts +0 -2
  144. package/lib/types/components/Button/Viewable.web.d.ts +3 -0
  145. package/lib/types/components/Collapse/Item/Item.web.d.ts +7 -0
  146. package/lib/types/components/SlimAlert/Alert.d.ts +1 -1
  147. package/lib/types/components/SlimAlert/PortalHost.d.ts +6 -0
  148. package/lib/types/components/SlimAlert/PortalHost.web.d.ts +6 -0
  149. package/package.json +9 -5
  150. package/src/components/ActionSheets/ActionSheets.tsx +0 -1
  151. package/src/components/ActionablePopover/ActionablePopover.tsx +3 -0
  152. package/src/components/Alert/Alert.tsx +5 -5
  153. package/src/components/Button/Viewable.web.tsx +44 -0
  154. package/src/components/Collapse/Item/Item.web.tsx +150 -0
  155. package/src/components/DatePicker/interface/index.ts +1 -0
  156. package/src/components/Image/index.ts +1 -1
  157. package/src/components/NoticeBar/NoticeBar.tsx +29 -5
  158. package/src/components/PickerView/PickerView.tsx +1 -1
  159. package/src/components/PickerView/Wheel.tsx +32 -3
  160. package/src/components/Popover/Popover.tsx +24 -26
  161. package/src/components/ProgressIndicator/ProgressIndicator.tsx +4 -12
  162. package/src/components/Sheets/AnimatedSheets.tsx +7 -3
  163. package/src/components/SlimAlert/Alert.tsx +9 -7
  164. package/src/components/SlimAlert/PortalHost.tsx +7 -0
  165. package/src/components/SlimAlert/PortalHost.web.tsx +11 -0
  166. package/src/components/Tag/Tag.tsx +7 -3
  167. package/src/components/TextField/TextField.tsx +19 -8
  168. package/src/components/TextView/TextView.tsx +15 -3
  169. package/src/components/Toast/Toast.tsx +2 -2
  170. package/src/i18n/@types/resources.d.ts +27 -27
  171. package/src/i18n/index.json +31 -31
  172. package/tsconfig.dts.json +1 -1
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
2
  import { RedsAlert } from "./interface";
3
- declare const Alert: React.FC<RedsAlert>;
3
+ declare const Alert: (props: RedsAlert) => React.JSX.Element;
4
4
  export default Alert;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ declare const PortalHost: ({ children, hostName }: {
3
+ children: React.ReactNode;
4
+ hostName: string | undefined;
5
+ }) => import("react").JSX.Element;
6
+ export default PortalHost;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ declare const PortalHost: ({ children, hostName }: {
3
+ children: React.ReactNode;
4
+ hostName: string;
5
+ }) => import("react").JSX.Element;
6
+ export default PortalHost;
@@ -1,5 +1,3 @@
1
- /// <reference types="react" />
2
- /// <reference types="node" />
3
1
  export declare const enum VideoSize {
4
2
  VERTICAL = "vertical",
5
3
  HORIZONTAL = "horizontal"
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ declare const Viewable: (props: any) => React.JSX.Element;
3
+ export default Viewable;
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { IItem } from "./interface/index";
3
+ declare const Item: {
4
+ ({ value, title, lazyRender, children, onClick }: IItem): React.JSX.Element;
5
+ defaultProps: IItem;
6
+ };
7
+ export default Item;
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
2
  import { RedsAlert } from "./interface";
3
- declare const Alert: React.FC<RedsAlert>;
3
+ declare const Alert: (props: RedsAlert) => React.JSX.Element | null;
4
4
  export default Alert;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ declare const PortalHost: ({ children, hostName }: {
3
+ children: React.ReactNode;
4
+ hostName: string | undefined;
5
+ }) => import("react").JSX.Element;
6
+ export default PortalHost;
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ declare const PortalHost: ({ children, hostName }: {
3
+ children: React.ReactNode;
4
+ hostName: string;
5
+ }) => import("react").JSX.Element;
6
+ export default PortalHost;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xhsreds/reds-rn-next",
3
- "version": "0.11.1-premode-test.0",
3
+ "version": "0.11.1-web202512221520",
4
4
  "author": "贾斌(呀哈) <jiabin@xiaohongshu.com>",
5
5
  "license": "ISC",
6
6
  "dependencies": {
@@ -9,8 +9,8 @@
9
9
  "@xhs/reds-apm": ">=0.0.1",
10
10
  "async-validator": "~4.2.5",
11
11
  "dayjs": "*",
12
- "runes": "~0.4.3",
13
- "react-native-url-polyfill": "*"
12
+ "react-native-url-polyfill": "*",
13
+ "runes": "~0.4.3"
14
14
  },
15
15
  "publishConfig": {
16
16
  "access": "public"
@@ -19,14 +19,14 @@
19
19
  "@xhs/lottie-react-native": "*",
20
20
  "@xhs/ozone-schema": "*",
21
21
  "@xhs/ozone-schema-web": "*",
22
+ "@xhs/react-native-harmony": "*",
22
23
  "@xhs/reder-icon-svg-ReDs_icon": "*",
24
+ "@xhs/reds-components": "*",
23
25
  "lottie-react-native": "7.1.0",
24
26
  "react": "*",
25
27
  "react-native": "*",
26
28
  "react-native-fs": "2.20.0",
27
29
  "react-native-svg": "13.14.0",
28
- "@xhs/react-native-harmony": "*",
29
- "@xhs/reds-components": "*",
30
30
  "@xhsreds/reds-token-next": "0.11.0"
31
31
  },
32
32
  "peerDependenciesMeta": {
@@ -42,6 +42,10 @@
42
42
  },
43
43
  "module": "./src/index.ts",
44
44
  "types": "./lib/types/index.d.ts",
45
+ "devDependencies": {
46
+ "@types/react-dom": "18.2.0",
47
+ "react-dom": "18.2.0"
48
+ },
45
49
  "scripts": {
46
50
  "test": "vitest --coverage",
47
51
  "bench": "vitest bench --outputJson benchmarks/out.json",
@@ -9,7 +9,6 @@ import useMounted from "../../pvCount/useUnmountedProcess";
9
9
  import { useLanguage } from "../LanguageProvider";
10
10
  import { getSafeAreaInsets } from "../StatusBar";
11
11
  import { typography } from "@xhs/reds-token-next";
12
- // test
13
12
  const ActionSheets = forwardRef((props: RedsActionSheets, ref) => {
14
13
  useMounted("ActionSheets");
15
14
  const themeColor = useThemeColor("ActionSheets");
@@ -223,6 +223,9 @@ export default ({
223
223
  }}
224
224
  onPressOut={(e) => {
225
225
  trigger === "touch" && onMaskChange(e, false);
226
+ if (Platform.OS === "web" && trigger === "click") {
227
+ onMaskChange(e, true);
228
+ }
226
229
  }}
227
230
  >
228
231
  <View
@@ -10,12 +10,12 @@ import {
10
10
  GestureResponderEvent,
11
11
  Animated,
12
12
  TouchableOpacity,
13
+ ViewStyle,
13
14
  } from "react-native";
14
15
  import { useThemeColor, useThemeTypography } from "../ConfigProvider";
15
16
  import { RedsAlert, AlertDefaultProps } from "./interface";
16
17
  import { Button } from "../Button";
17
- import { Divider } from "../Divider";
18
- import { Portal } from "../Portal";
18
+ import PortalHost from "../SlimAlert/PortalHost";
19
19
  import { style } from "./styles";
20
20
  import useMounted from "../../pvCount/useUnmountedProcess";
21
21
  import { useLanguage } from "../LanguageProvider";
@@ -143,8 +143,8 @@ const Alert: React.FC<RedsAlert> = (props) => {
143
143
  };
144
144
  useMounted("Alert");
145
145
  return show ? (
146
- <Portal hostName={hostName}>
147
- <View style={styles.centeredView}>
146
+ <PortalHost hostName={props.hostName}>
147
+ <View style={[styles.centeredView, { position: props.hostName ? "absolute" : "fixed" } as ViewStyle]}>
148
148
  {mask && (
149
149
  <TouchableWithoutFeedback onPress={onMask}>
150
150
  <View style={styles.modalOverlay} />
@@ -241,7 +241,7 @@ const Alert: React.FC<RedsAlert> = (props) => {
241
241
  </View>
242
242
  </Animated.View>
243
243
  </View>
244
- </Portal>
244
+ </PortalHost>
245
245
  ) : null;
246
246
  };
247
247
 
@@ -0,0 +1,44 @@
1
+ import React, { useEffect, useRef } from "react";
2
+ import { View, Dimensions } from "react-native";
3
+
4
+ const Viewable = (props: any) => {
5
+ const { style, percent = 1, callback, ...rest } = props;
6
+ const targetRef = useRef<View>(null);
7
+ const hasLoggedExposure = useRef(false);
8
+
9
+ useEffect(() => {
10
+ if (typeof window === "undefined") return;
11
+
12
+ const observer = new IntersectionObserver(
13
+ (entries) => {
14
+ entries.forEach((entry) => {
15
+ if (entry.isIntersecting && entry.intersectionRatio >= (percent || 1)) {
16
+ if (!hasLoggedExposure.current) {
17
+ hasLoggedExposure.current = true;
18
+ callback?.();
19
+ }
20
+ }
21
+ });
22
+ },
23
+ {
24
+ threshold: percent || 1,
25
+ },
26
+ );
27
+
28
+ // 获取实际的 DOM 元素
29
+ const domNode = targetRef.current as any;
30
+ if (domNode) {
31
+ observer.observe(domNode);
32
+ }
33
+
34
+ return () => observer.disconnect();
35
+ }, [callback, percent]);
36
+
37
+ return (
38
+ <View ref={targetRef} style={style} {...rest}>
39
+ {props.children}
40
+ </View>
41
+ );
42
+ };
43
+
44
+ export default Viewable;
@@ -0,0 +1,150 @@
1
+ import React, { useState, useRef, useEffect, useMemo } from "react";
2
+ import { View, Text, TouchableWithoutFeedback, LayoutChangeEvent, ViewStyle } from "react-native";
3
+ import { IItem, ItemDefaultProps } from "./interface/index";
4
+ import createStyles from "./styles";
5
+ import { Icon } from "../../Icon";
6
+ import { ArrowUpM, ArrowDownCenterB } from "@xhs/reder-icon-svg-ReDs_icon";
7
+ import { CollapseContext } from "../hooks/useCollapseContext";
8
+ import { useThemeColor } from "../../ConfigProvider";
9
+
10
+ const Item = ({ value, title, lazyRender, children, onClick }: IItem) => {
11
+ const { addActiveValue, isActiveValue, removeActiveValue, size, registerChild, unregisterChild } =
12
+ React.useContext(CollapseContext);
13
+ const styles = createStyles(size || "Medium");
14
+ const [visible, setVisible] = useState(false);
15
+ const [shouldMount, setShouldMount] = useState(!lazyRender);
16
+ const [contentHeight, setContentHeight] = useState(0);
17
+ const firstRender = useRef(false);
18
+ const measureRef = useRef<View>(null);
19
+ const contentRef = useRef<View>(null);
20
+
21
+ const themeColor = useThemeColor();
22
+ const [lineItem, setLineItem] = useState(false);
23
+
24
+ const childInfo = {
25
+ setLine: (value: boolean) => setLineItem(value),
26
+ };
27
+
28
+ useEffect(() => {
29
+ registerChild(childInfo);
30
+ return () => unregisterChild(childInfo);
31
+ }, []);
32
+
33
+ const [initialMeasureDone, setInitialMeasureDone] = useState(false);
34
+
35
+ const setFirstRenderTag = () => {
36
+ firstRender.current = true;
37
+ setShouldMount(true);
38
+ };
39
+
40
+ const handleContentLayout = (event: LayoutChangeEvent) => {
41
+ const measuredHeight = event.nativeEvent.layout.height;
42
+ if (measuredHeight !== contentHeight) {
43
+ setContentHeight(measuredHeight);
44
+ setInitialMeasureDone(true);
45
+ }
46
+ };
47
+
48
+ // 初始可见状态同步逻辑
49
+ useEffect(() => {
50
+ const isActive = !!isActiveValue?.(value);
51
+ if (isActive) {
52
+ measureRef.current?.measure?.((x, y, width, height) => {
53
+ setContentHeight(height);
54
+ setInitialMeasureDone(true);
55
+ });
56
+ }
57
+ setVisible(isActive);
58
+ if (!firstRender.current && isActive) {
59
+ setFirstRenderTag();
60
+ }
61
+ }, [isActiveValue?.(value)]);
62
+
63
+ const onPress = () => {
64
+ const nextActive = !isActiveValue?.(value);
65
+
66
+ if (nextActive) {
67
+ addActiveValue?.(value);
68
+ if (!firstRender.current) setFirstRenderTag();
69
+ } else {
70
+ removeActiveValue?.(value);
71
+ }
72
+
73
+ setVisible(nextActive);
74
+ onClick?.(value);
75
+ };
76
+
77
+ const cloneChildren = useMemo(() => {
78
+ return React.Children.map(children, (child: any) => {
79
+ return React.cloneElement(child, {
80
+ style: { color: themeColor.Paragraph },
81
+ ...child.props,
82
+ });
83
+ });
84
+ }, [children]);
85
+
86
+ return (
87
+ <View>
88
+ <TouchableWithoutFeedback onPress={onPress}>
89
+ <View style={styles.header}>
90
+ <Text style={styles.title}>{title}</Text>
91
+ <View
92
+ style={
93
+ { transform: `rotate(${visible ? 180 : 0}deg)`, transition: "transform 200ms ease-in-out" } as ViewStyle
94
+ }
95
+ >
96
+ <Icon icon={ArrowDownCenterB} size={16} fill={themeColor.Title} />
97
+ </View>
98
+ </View>
99
+ </TouchableWithoutFeedback>
100
+
101
+ {/* 测量视图 */}
102
+ <View
103
+ ref={measureRef}
104
+ onLayout={handleContentLayout}
105
+ style={{
106
+ position: "absolute",
107
+ opacity: 0,
108
+ paddingHorizontal: 16,
109
+ paddingBottom: 12,
110
+ top: -9999,
111
+ width: "100%",
112
+ ...styles.content,
113
+ }}
114
+ >
115
+ {cloneChildren}
116
+ </View>
117
+
118
+ {/* Web 内容视图 */}
119
+ <View
120
+ ref={contentRef}
121
+ style={{
122
+ overflow: "hidden",
123
+ height: visible ? contentHeight : 0,
124
+ paddingHorizontal: 16,
125
+ paddingBottom: visible ? 12 : 0,
126
+ minHeight: visible ? 1 : 0,
127
+ // @ts-expect-error
128
+ transition: "height 200ms ease-in-out, padding 200ms ease-in-out, opacity 200ms ease-in-out",
129
+ ...styles.content,
130
+ }}
131
+ >
132
+ {cloneChildren}
133
+ </View>
134
+
135
+ {/* 分割线 */}
136
+ {lineItem && (
137
+ <View
138
+ style={{
139
+ backgroundColor: themeColor.Separator,
140
+ height: 0.5,
141
+ marginHorizontal: 16,
142
+ }}
143
+ />
144
+ )}
145
+ </View>
146
+ );
147
+ };
148
+
149
+ Item.defaultProps = ItemDefaultProps;
150
+ export default Item;
@@ -1,3 +1,4 @@
1
+ import { Platform } from "react-native";
1
2
  export enum DatePickerMode {
2
3
  YearMonthDay = "yearmonthday",
3
4
  YearMonth = "yearmonth",
@@ -3,6 +3,6 @@ import Image from "./Image";
3
3
  import Image69 from "./Image69";
4
4
  import * as ImageType from "./interface";
5
5
 
6
- const ImageComponent = Platform.constants?.reactNativeVersion?.minor === 72 ? Image : Image69;
6
+ const ImageComponent = Platform.constants?.reactNativeVersion?.minor === 72 || Platform.OS === "web" ? Image : Image69;
7
7
  export default ImageComponent;
8
8
  export { ImageComponent as Image, ImageType, Image69 };
@@ -1,10 +1,30 @@
1
1
  import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
2
- import { View, TouchableWithoutFeedback, Text, Image, Animated, Easing } from "react-native";
2
+ import {
3
+ View,
4
+ TouchableWithoutFeedback,
5
+ Text,
6
+ Image,
7
+ Animated,
8
+ Easing,
9
+ LayoutChangeEvent,
10
+ Platform,
11
+ TextStyle,
12
+ } from "react-native";
3
13
  import { RedsNoticeBar, NoticeBarDefaultProps, NoticeBarType, NoticeBarActionType } from "./interface/index";
4
14
  import getStyles from "./styles";
5
15
  import { useThemeColor } from "../ConfigProvider";
6
16
  import { useLanguage } from "../LanguageProvider";
7
17
  import useMounted from "../../pvCount/useUnmountedProcess";
18
+
19
+ const AnimatedTextStyle =
20
+ Platform.OS === "web"
21
+ ? {
22
+ textOverflow: "initial",
23
+ overflow: "initial",
24
+ maxWidth: "auto",
25
+ }
26
+ : {};
27
+
8
28
  const NoticeBar = (props: RedsNoticeBar) => {
9
29
  useMounted("NoticeBar");
10
30
  const [_visible, setVisible] = useState(true);
@@ -52,7 +72,7 @@ const NoticeBar = (props: RedsNoticeBar) => {
52
72
  const scrollDistance = useMemo(() => Math.max(textWidth - containerWidth, 0), [textWidth, containerWidth]);
53
73
 
54
74
  useEffect(() => {
55
- if (props.type === NoticeBarType.SCROLLABLE && textWidth > 0) {
75
+ if (props.type === NoticeBarType.SCROLLABLE && textWidth > 0 && scrollDistance > 0) {
56
76
  const startScrolling = () => {
57
77
  scrollX.setValue(0);
58
78
  Animated.timing(scrollX, {
@@ -84,6 +104,10 @@ const NoticeBar = (props: RedsNoticeBar) => {
84
104
  setVisible(!!props.visible);
85
105
  }, [props.visible]);
86
106
 
107
+ const handleAnimatedTextLayout = (e: LayoutChangeEvent) => {
108
+ setTextWidth(e.nativeEvent.layout.width);
109
+ };
110
+
87
111
  return _visible ? (
88
112
  <View
89
113
  style={[
@@ -100,11 +124,11 @@ const NoticeBar = (props: RedsNoticeBar) => {
100
124
  onLayout={(e) => setContainerWidth(e.nativeEvent.layout.width)}
101
125
  >
102
126
  {props.type === NoticeBarType.SCROLLABLE ? (
103
- <View style={{ minHeight: 18, overflow: "scroll", flexDirection: "row" }}>
127
+ <View style={{ minHeight: 18, overflow: Platform.OS === "web" ? "hidden" : "scroll", flexDirection: "row" }}>
104
128
  <Animated.Text
105
129
  numberOfLines={1}
106
- style={[{ transform: [{ translateX: scrollX }] }]}
107
- onLayout={(e) => setTextWidth(e.nativeEvent.layout.width)}
130
+ style={[{ transform: [{ translateX: scrollX }] }, AnimatedTextStyle as TextStyle]}
131
+ onLayout={handleAnimatedTextLayout}
108
132
  >
109
133
  <Text style={styles.text}>{props.content}</Text>
110
134
  <Text style={styles.text}>{" "}</Text>
@@ -47,7 +47,7 @@ const PickerView = (props: RedsPickerView) => {
47
47
  <ProgressIndicator type="default" />
48
48
  </View>
49
49
  ) : (
50
- <View style={[styles.wheelWrapper, { backgroundColor: themeColor.Bg2 }]}>
50
+ <View style={[styles.wheelWrapper, { backgroundColor: themeColor.Bg2, overflow: "scroll" }]}>
51
51
  {columns.map((column, colIndex) => (
52
52
  <Wheel
53
53
  key={colIndex}
@@ -1,5 +1,13 @@
1
1
  import React, { useRef, useState, useEffect } from "react";
2
- import { NativeScrollEvent, NativeSyntheticEvent, ScrollView, View, Text, TouchableNativeFeedback } from "react-native";
2
+ import {
3
+ NativeScrollEvent,
4
+ NativeSyntheticEvent,
5
+ ScrollView,
6
+ View,
7
+ Text,
8
+ TouchableNativeFeedback,
9
+ Platform,
10
+ } from "react-native";
3
11
  import { useThemeColor } from "../ConfigProvider";
4
12
  import { typography } from "@xhs/reds-token-next";
5
13
  import { RedsWheel, Column } from "./interface/index";
@@ -143,7 +151,12 @@ const Wheel = (props: RedsWheel) => {
143
151
  */
144
152
  const renderItems = () => {
145
153
  return column.map((item, index) => (
146
- <TouchableNativeFeedback onPress={() => handleClick(index)} key={item.value}>
154
+ <TouchableNativeFeedback
155
+ onPress={() => handleClick(index)}
156
+ key={item.value}
157
+ // @ts-expect-error
158
+ style={Platform.OS === "web" ? { border: "none", alignSelf: "inherit" } : {}}
159
+ >
147
160
  <View
148
161
  style={[styles.wheel, { height: itemHeight, backgroundColor: themeColor.Bg2 }]}
149
162
  key={item.value}
@@ -157,9 +170,25 @@ const Wheel = (props: RedsWheel) => {
157
170
  ));
158
171
  };
159
172
 
173
+ useEffect(() => {
174
+ if (Platform.OS !== "web") {
175
+ return;
176
+ }
177
+ const handleScrollEnd = (e: any) => {
178
+ const selectIndex = Math.round(e.target.scrollTop / itemHeight);
179
+ setIndex(selectIndex);
180
+ };
181
+ // @ts-expect-error
182
+ scrollerRef.current?.addEventListener("scrollend", handleScrollEnd);
183
+ return () => {
184
+ // @ts-expect-error
185
+ scrollerRef.current?.removeEventListener("scrollend", handleScrollEnd);
186
+ };
187
+ }, [scrollerRef.current, itemHeight]);
188
+
160
189
  return (
161
190
  <ScrollView
162
- style={{ flex: 1 }}
191
+ style={{ flex: 1, height: "100%" }}
163
192
  nestedScrollEnabled
164
193
  horizontal={false}
165
194
  ref={(el: any) => (scrollerRef.current = el)}
@@ -1,5 +1,15 @@
1
1
  import React, { useState, useMemo, isValidElement, useEffect, useRef } from "react";
2
- import { Text, View, TouchableWithoutFeedback, GestureResponderEvent, Animated, Image, Dimensions } from "react-native";
2
+ import {
3
+ Text,
4
+ View,
5
+ TouchableWithoutFeedback,
6
+ GestureResponderEvent,
7
+ Animated,
8
+ Image,
9
+ Dimensions,
10
+ Platform,
11
+ LayoutChangeEvent,
12
+ } from "react-native";
3
13
  import { RedsPopover } from "./interface/index";
4
14
  import { ModalWrapper } from "./component";
5
15
  import { darkColor, lightColor, typography } from "@xhs/reds-token-next";
@@ -33,6 +43,8 @@ export default ({
33
43
  const needModal = useMemo(() => opacity !== 0, [opacity]);
34
44
 
35
45
  const [_visible, setVisible] = useState(false);
46
+ const [floatStyles, setFloatStyles] = useState({});
47
+ const [arrowStyles, setArrowStyles] = useState({});
36
48
 
37
49
  const progress = useRef(new Animated.Value(0)).current;
38
50
 
@@ -45,21 +57,15 @@ export default ({
45
57
  height: 0,
46
58
  });
47
59
 
48
- const [floatingLayout, setFloatingLayout] = useState({
49
- x: defaultValue,
50
- y: defaultValue,
51
- width: 0,
52
- height: 0,
53
- });
54
-
55
- const floatStyles = useMemo(() => {
60
+ const handleFloatingLayout = (e: LayoutChangeEvent) => {
61
+ const floatingLayout = e.nativeEvent.layout;
56
62
  const start = ["top-start", "bottom-start"].includes(placement);
57
63
  const mid = ["top", "bottom"].includes(placement);
58
64
  const end = ["top-end", "bottom-end"].includes(placement);
59
65
  const diffX = floatingLayout.width - layout.width;
60
66
  // @ts-expect-error
61
67
  const isHarmony = Platform.OS === "harmony";
62
- return layout.height
68
+ const floatStyles = layout.height
63
69
  ? {
64
70
  position: "absolute",
65
71
  top:
@@ -71,16 +77,7 @@ export default ({
71
77
  (isHarmony ? Dimensions.get("screen").width : 0),
72
78
  }
73
79
  : {};
74
- }, [placement, layout, floatingLayout]);
75
-
76
- const arrowStyles = useMemo(() => {
77
- const start = ["top-start", "bottom-start"].includes(placement);
78
- const mid = ["top", "bottom"].includes(placement);
79
- const end = ["top-end", "bottom-end"].includes(placement);
80
- const diffX = floatingLayout.width - layout.width;
81
- // @ts-expect-error
82
- const isHarmony = Platform.OS === "harmony";
83
- return layout.height
80
+ const arrowStyles = layout.height
84
81
  ? {
85
82
  transform: [{ rotate: placement.includes("top") ? `0deg` : `180deg` }],
86
83
  position: "absolute",
@@ -101,7 +98,9 @@ export default ({
101
98
  (isHarmony ? Dimensions.get("screen").width : 0),
102
99
  }
103
100
  : {};
104
- }, [placement, layout, floatingLayout, offset]);
101
+ setFloatStyles(floatStyles);
102
+ setArrowStyles(arrowStyles);
103
+ };
105
104
 
106
105
  useEffect(() => {
107
106
  let timer: any;
@@ -212,6 +211,9 @@ export default ({
212
211
  }}
213
212
  onPressOut={(e) => {
214
213
  trigger === "touch" && onMaskChange(e, false);
214
+ if (Platform.OS === "web" && trigger === "click") {
215
+ onMaskChange(e, true);
216
+ }
215
217
  }}
216
218
  >
217
219
  <View
@@ -240,10 +242,7 @@ export default ({
240
242
  <>
241
243
  <Animated.View
242
244
  collapsable={false}
243
- onLayout={(e) => {
244
- setFloatingLayout(e.nativeEvent.layout);
245
- }}
246
- // @ts-expect-error
245
+ onLayout={handleFloatingLayout}
247
246
  style={{
248
247
  backgroundColor: popoverStyle.backgroundColor,
249
248
  paddingHorizontal: 12,
@@ -279,7 +278,6 @@ export default ({
279
278
  </Animated.View>
280
279
  <Image
281
280
  source={{ uri: angle }}
282
- // @ts-expect-error
283
281
  style={{
284
282
  width: 14,
285
283
  height: 6,
@@ -79,6 +79,7 @@ const ProgressIndicator = (props: RedsProgressIndicator) => {
79
79
 
80
80
  const LottieView = React.useMemo(() => {
81
81
  const lottieSource = getLottieSource(type as TLottieSourceType)[strokeColor || colorMode || "light"];
82
+ // TODO: lottie-react-native 不能使用 progress,需要单独适配 web
82
83
  if (type === "progress") {
83
84
  let progress = 0;
84
85
  if (percent > 100) {
@@ -89,9 +90,7 @@ const ProgressIndicator = (props: RedsProgressIndicator) => {
89
90
  return (
90
91
  <>
91
92
  {showPercent && <Text style={[styles.percentText, textStyle]}>{formatText(percent)}</Text>}
92
- {Platform.OS !== "web" && (
93
- <Lottie style={{ flex: 1 }} progress={progress} source={props.lottieSource || lottieSource} />
94
- )}
93
+ <Lottie style={{ flex: 1 }} progress={progress} source={props.lottieSource || lottieSource} />
95
94
  <></>
96
95
  </>
97
96
  );
@@ -99,19 +98,12 @@ const ProgressIndicator = (props: RedsProgressIndicator) => {
99
98
  if (colorMode === "light") {
100
99
  return (
101
100
  <>
102
- {Platform.OS !== "web" && (
103
- <Lottie style={{ flex: 1 }} useNativeLooping autoPlay loop source={props.lottieSource || lottieSource} />
104
- )}
101
+ <Lottie style={{ flex: 1 }} useNativeLooping autoPlay loop source={props.lottieSource || lottieSource} />
105
102
  <></>
106
103
  </>
107
104
  );
108
105
  }
109
- return (
110
- Platform.OS !== "web" && (
111
- <Lottie style={{ flex: 1 }} useNativeLooping autoPlay loop source={props.lottieSource || lottieSource} />
112
- )
113
- );
114
- // return <></>;
106
+ return <Lottie style={{ flex: 1 }} useNativeLooping autoPlay loop source={props.lottieSource || lottieSource} />;
115
107
  }, [type, colorMode, percent, strokeColor]);
116
108
 
117
109
  return (