@unif/react-native-design 0.5.1 → 0.7.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 (61) hide show
  1. package/README.md +60 -10
  2. package/lib/module/components/ui/Confirm/ConfirmHost.js +57 -83
  3. package/lib/module/components/ui/Confirm/ConfirmHost.js.map +1 -1
  4. package/lib/module/components/ui/Confirm/styles.js +14 -8
  5. package/lib/module/components/ui/Confirm/styles.js.map +1 -1
  6. package/lib/module/components/ui/Toast/ToastHost.js +23 -3
  7. package/lib/module/components/ui/Toast/ToastHost.js.map +1 -1
  8. package/lib/module/components/ui/Toast/styles.js +1 -1
  9. package/lib/module/components/ui/Toast/styles.js.map +1 -1
  10. package/lib/module/components/ui/Toast/toast.js +4 -2
  11. package/lib/module/components/ui/Toast/toast.js.map +1 -1
  12. package/lib/module/components/ui/index.js +0 -1
  13. package/lib/module/components/ui/index.js.map +1 -1
  14. package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts +4 -3
  15. package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts.map +1 -1
  16. package/lib/typescript/src/components/ui/Confirm/styles.d.ts +11 -5
  17. package/lib/typescript/src/components/ui/Confirm/styles.d.ts.map +1 -1
  18. package/lib/typescript/src/components/ui/Input/Input.d.ts +3 -3
  19. package/lib/typescript/src/components/ui/Search/Search.d.ts +3 -3
  20. package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts +3 -3
  21. package/lib/typescript/src/components/ui/Textarea/Textarea.d.ts +3 -3
  22. package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts +3 -0
  23. package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts.map +1 -1
  24. package/lib/typescript/src/components/ui/Toast/index.d.ts +1 -1
  25. package/lib/typescript/src/components/ui/Toast/index.d.ts.map +1 -1
  26. package/lib/typescript/src/components/ui/Toast/styles.d.ts +0 -1
  27. package/lib/typescript/src/components/ui/Toast/styles.d.ts.map +1 -1
  28. package/lib/typescript/src/components/ui/Toast/toast.d.ts.map +1 -1
  29. package/lib/typescript/src/components/ui/Toast/types.d.ts +9 -3
  30. package/lib/typescript/src/components/ui/Toast/types.d.ts.map +1 -1
  31. package/lib/typescript/src/components/ui/index.d.ts +1 -3
  32. package/lib/typescript/src/components/ui/index.d.ts.map +1 -1
  33. package/package.json +6 -3
  34. package/src/components/ui/Confirm/ConfirmHost.tsx +60 -103
  35. package/src/components/ui/Confirm/styles.ts +14 -8
  36. package/src/components/ui/Toast/ToastHost.tsx +20 -3
  37. package/src/components/ui/Toast/index.ts +1 -0
  38. package/src/components/ui/Toast/styles.ts +1 -1
  39. package/src/components/ui/Toast/toast.ts +2 -1
  40. package/src/components/ui/Toast/types.ts +10 -3
  41. package/src/components/ui/index.ts +1 -2
  42. package/lib/module/components/ui/BottomSheet/BottomSheet.js +0 -104
  43. package/lib/module/components/ui/BottomSheet/BottomSheet.js.map +0 -1
  44. package/lib/module/components/ui/BottomSheet/index.js +0 -4
  45. package/lib/module/components/ui/BottomSheet/index.js.map +0 -1
  46. package/lib/module/components/ui/BottomSheet/styles.js +0 -26
  47. package/lib/module/components/ui/BottomSheet/styles.js.map +0 -1
  48. package/lib/module/components/ui/BottomSheet/types.js +0 -4
  49. package/lib/module/components/ui/BottomSheet/types.js.map +0 -1
  50. package/lib/typescript/src/components/ui/BottomSheet/BottomSheet.d.ts +0 -4
  51. package/lib/typescript/src/components/ui/BottomSheet/BottomSheet.d.ts.map +0 -1
  52. package/lib/typescript/src/components/ui/BottomSheet/index.d.ts +0 -3
  53. package/lib/typescript/src/components/ui/BottomSheet/index.d.ts.map +0 -1
  54. package/lib/typescript/src/components/ui/BottomSheet/styles.d.ts +0 -23
  55. package/lib/typescript/src/components/ui/BottomSheet/styles.d.ts.map +0 -1
  56. package/lib/typescript/src/components/ui/BottomSheet/types.d.ts +0 -26
  57. package/lib/typescript/src/components/ui/BottomSheet/types.d.ts.map +0 -1
  58. package/src/components/ui/BottomSheet/BottomSheet.tsx +0 -117
  59. package/src/components/ui/BottomSheet/index.ts +0 -2
  60. package/src/components/ui/BottomSheet/styles.ts +0 -20
  61. package/src/components/ui/BottomSheet/types.ts +0 -26
@@ -1,5 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from 'react';
2
2
  import { Text, View } from 'react-native';
3
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
3
4
  import Animated, {
4
5
  cancelAnimation,
5
6
  runOnJS,
@@ -7,7 +8,7 @@ import Animated, {
7
8
  useSharedValue,
8
9
  withTiming,
9
10
  } from 'react-native-reanimated';
10
- import { useColors, useThemedStyles, motion } from '../../../theme';
11
+ import { useColors, useThemedStyles, motion, space } from '../../../theme';
11
12
  import { dotColorFor, makeStyles } from './styles';
12
13
  import { _subs } from './toast';
13
14
  import type { Subscriber, ToastEntry, ToastHostProps } from './types';
@@ -15,12 +16,16 @@ import type { Subscriber, ToastEntry, ToastHostProps } from './types';
15
16
  /**
16
17
  * 在根附近挂一次。监听 toast() 调用并渲染当前 toast。
17
18
  * 同一时间只显示一条 —— 新的会替换旧的。
19
+ *
20
+ * 位置由 `entry.position`('top' / 'bottom' / 'center')决定,top/bottom 自动避让
21
+ * safe-area;进入动画方向随位置(top 从上滑、bottom/center 从下滑)。
18
22
  */
19
23
  export function ToastHost({
20
24
  testID,
21
25
  }: ToastHostProps = {}): React.JSX.Element | null {
22
26
  const c = useColors();
23
27
  const styles = useThemedStyles(makeStyles);
28
+ const insets = useSafeAreaInsets();
24
29
  const [entry, setEntry] = useState<ToastEntry | null>(null);
25
30
  const op = useSharedValue(0);
26
31
  const ty = useSharedValue(8);
@@ -39,14 +44,18 @@ export function ToastHost({
39
44
 
40
45
  useEffect(() => {
41
46
  if (!entry) return;
47
+ // 进入方向:top 从上(-8)滑入,bottom / center 从下(8)滑入
48
+ const from = entry.position === 'top' ? -8 : 8;
42
49
  cancelAnimation(op);
43
50
  cancelAnimation(ty);
51
+ op.value = 0;
52
+ ty.value = from;
44
53
  op.value = withTiming(1, { duration: motion.base });
45
54
  ty.value = withTiming(0, { duration: motion.base });
46
55
 
47
56
  dismissTimer.current = setTimeout(() => {
48
57
  op.value = withTiming(0, { duration: motion.base });
49
- ty.value = withTiming(8, { duration: motion.base }, (finished) => {
58
+ ty.value = withTiming(from, { duration: motion.base }, (finished) => {
50
59
  if (finished) runOnJS(setEntry)(null);
51
60
  });
52
61
  }, entry.duration);
@@ -65,10 +74,18 @@ export function ToastHost({
65
74
 
66
75
  if (!entry) return null;
67
76
 
77
+ // 位置:top=顶部(safe-area + 间距)/ center=屏幕居中 / bottom=底部(默认)
78
+ const posStyle =
79
+ entry.position === 'top'
80
+ ? { top: insets.top + space[10] }
81
+ : entry.position === 'center'
82
+ ? { top: 0, bottom: 0, justifyContent: 'center' as const }
83
+ : { bottom: insets.bottom + space[10] };
84
+
68
85
  const dotColor = dotColorFor(entry.kind, c);
69
86
 
70
87
  return (
71
- <View style={styles.host} pointerEvents="none" testID={testID}>
88
+ <View style={[styles.host, posStyle]} pointerEvents="none" testID={testID}>
72
89
  <Animated.View style={[styles.toast, animatedStyle]}>
73
90
  {dotColor ? (
74
91
  <View style={[styles.dot, { backgroundColor: dotColor }]} />
@@ -5,4 +5,5 @@ export type {
5
5
  ToastHostProps,
6
6
  ToastInput,
7
7
  ToastKind,
8
+ ToastPosition,
8
9
  } from './types';
@@ -6,10 +6,10 @@ import type { ToastKind } from './types';
6
6
  export const makeStyles = (c: ColorTokens) =>
7
7
  StyleSheet.create({
8
8
  host: {
9
+ // 定位(top/bottom/center)由 ToastHost 按 entry.position 注入,这里只留通用
9
10
  position: 'absolute',
10
11
  left: 0,
11
12
  right: 0,
12
- bottom: space[10],
13
13
  alignItems: 'center',
14
14
  // zIndex: toast 浮层 —— 盖在 Screen 内容之上(navigator / overlay 之下)。
15
15
  // 同级兄弟节点无 z 顺序需求,但作为 absolute 浮岛对其他屏内 absolute 节点
@@ -11,12 +11,13 @@ export const _subs = new Set<Subscriber>();
11
11
  function emit(input: ToastInput, kind: ToastKind = 'info') {
12
12
  const entry: ToastEntry =
13
13
  typeof input === 'string'
14
- ? { id: ++_id, message: input, kind, duration: 3000 }
14
+ ? { id: ++_id, message: input, kind, duration: 3000, position: 'bottom' }
15
15
  : {
16
16
  id: ++_id,
17
17
  message: input.message,
18
18
  kind: input.kind ?? kind,
19
19
  duration: input.duration ?? 3000,
20
+ position: input.position ?? 'bottom',
20
21
  };
21
22
  _subs.forEach((s) => s(entry));
22
23
  }
@@ -1,10 +1,13 @@
1
1
  /** Toast 类型:info=灰点 / success=绿点 / error=红点 */
2
2
  export type ToastKind = 'info' | 'success' | 'error';
3
3
 
4
+ /** Toast 显示位置:top=顶部 / bottom=底部(默认) / center=屏幕居中 */
5
+ export type ToastPosition = 'top' | 'bottom' | 'center';
6
+
4
7
  /**
5
8
  * `toast(...)` 调用入参:
6
- * - 字符串简写:默认 info kind 2200ms duration
7
- * - 对象形式:可指定 kind duration
9
+ * - 字符串简写:默认 info kind、bottom 位置、3000ms duration
10
+ * - 对象形式:可指定 kind / duration / position
8
11
  */
9
12
  export type ToastInput =
10
13
  | string
@@ -13,8 +16,10 @@ export type ToastInput =
13
16
  message: string;
14
17
  /** Toast 类型,默认 'info' */
15
18
  kind?: ToastKind;
16
- /** 自动消失毫秒数,默认 2200 */
19
+ /** 自动消失毫秒数,默认 3000 */
17
20
  duration?: number;
21
+ /** 显示位置,默认 'bottom' */
22
+ position?: ToastPosition;
18
23
  };
19
24
 
20
25
  export type ToastEntry = {
@@ -26,6 +31,8 @@ export type ToastEntry = {
26
31
  kind: ToastKind;
27
32
  /** 显示毫秒数 */
28
33
  duration: number;
34
+ /** 显示位置 */
35
+ position: ToastPosition;
29
36
  };
30
37
 
31
38
  /** Toast 订阅者函数签名(ToastHost 内部用) */
@@ -1,7 +1,5 @@
1
1
  export { Avatar } from './Avatar';
2
2
  export type { AvatarProps, AvatarSize, AvatarVariant } from './Avatar';
3
- export { BottomSheet } from './BottomSheet';
4
- export type { BottomSheetProps } from './BottomSheet';
5
3
  export { BlurLayer } from './BlurLayer';
6
4
  export type { BlurLayerProps } from './BlurLayer';
7
5
  export { Button } from './Button';
@@ -80,4 +78,5 @@ export type {
80
78
  ToastHostProps,
81
79
  ToastInput,
82
80
  ToastKind,
81
+ ToastPosition,
83
82
  } from './Toast';
@@ -1,104 +0,0 @@
1
- "use strict";
2
-
3
- import React, { useCallback, useMemo } from 'react';
4
- import { View } from 'react-native';
5
- import GorhomBottomSheet, { BottomSheetBackdrop, BottomSheetScrollView } from '@gorhom/bottom-sheet';
6
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
7
- import { useThemedStyles } from "../../../theme/index.js";
8
- import { BlurLayer } from "../BlurLayer/index.js";
9
- import { makeStyles } from "./styles.js";
10
- import { jsx as _jsx } from "react/jsx-runtime";
11
- /** 底部 sheet —— @gorhom/bottom-sheet 的薄壳层。
12
- *
13
- * 适合 navigation `presentation: 'transparentModal'` 屏内 root 用法:mount 时
14
- * 默认 animateOnMount=true 从 -1 动画到 index=0,goBack() 自然关闭。
15
- * state-driven sheet 应用 @gorhom 原生 `<BottomSheetModal>`,本 wrapper 不覆盖。
16
- *
17
- * - `snapPoints` 必传(`['50%']` / `['50%', '90%']` 等)
18
- * - `backdrop` 三档:`'scrim'` / `'blur'`(BlurLayer)/ `'none'` */
19
- // 默认 30% / 60% / 95%,模块顶层 const 引用稳定。
20
- const DEFAULT_SNAP_POINTS = ['30%', '60%', '95%'];
21
- export function BottomSheet({
22
- snapPoints = DEFAULT_SNAP_POINTS,
23
- children,
24
- sheetStyle,
25
- backdrop = 'scrim',
26
- grabber = true,
27
- onClose,
28
- testID
29
- }) {
30
- const styles = useThemedStyles(makeStyles);
31
-
32
- /** BlurView backdrop —— 复用 @gorhom BottomSheetBackdrop 的手势 + animatedIndex
33
- * 插值,opacity=1 + bg=transparent 让 backdrop 本身不画 scrim,只画 BlurLayer。
34
- * tap-to-close + opacity 淡入 / pointer-events disable 全部继承自 @gorhom 内核。
35
- *
36
- * useCallback + styles dep 保引用稳定(主题切换时才重建),避免每次渲染新引用让
37
- * @gorhom 内部 memo 失效 / remount backdrop 树。 */
38
- const BlurBackdrop = useCallback(props => /*#__PURE__*/_jsx(BottomSheetBackdrop, {
39
- ...props,
40
- appearsOnIndex: 0,
41
- disappearsOnIndex: -1,
42
- opacity: 1,
43
- style: [props.style, styles.backdropTransparent],
44
- children: /*#__PURE__*/_jsx(BlurLayer, {
45
- intensity: "strong"
46
- })
47
- }), [styles.backdropTransparent]);
48
-
49
- /** Scrim backdrop —— 走 c.scrim token(亮 rgba(0,0,0,0.5) / 暗 0.7),opacity=1
50
- * 让 @gorhom 只跑透明度淡入动画,scrim 实色由 token 决定 → 暗色自动加深。 */
51
- const ScrimBackdrop = useCallback(props => /*#__PURE__*/_jsx(BottomSheetBackdrop, {
52
- ...props,
53
- appearsOnIndex: 0,
54
- disappearsOnIndex: -1,
55
- opacity: 1,
56
- style: [props.style, styles.scrimBackdrop]
57
- }), [styles.scrimBackdrop]);
58
- const renderBackdrop = useMemo(() => {
59
- switch (backdrop) {
60
- case 'none':
61
- return undefined;
62
- case 'blur':
63
- return BlurBackdrop;
64
- case 'scrim':
65
- return ScrimBackdrop;
66
- }
67
- }, [backdrop, BlurBackdrop, ScrimBackdrop]);
68
-
69
- // @gorhom onChange:index === -1 即关闭。配合 transparentModal route 必传
70
- // caller 的 onClose → navigation.goBack(),否则路由 stack 不 pop,native overlay 继续吞触摸。
71
- const onChange = index => {
72
- if (index === -1) onClose?.();
73
- };
74
- return /*#__PURE__*/_jsx(GestureHandlerRootView, {
75
- style: styles.root,
76
- children: /*#__PURE__*/_jsx(GorhomBottomSheet, {
77
- snapPoints: snapPoints,
78
- index: 0,
79
- backdropComponent: renderBackdrop,
80
- handleComponent: grabber ? undefined : null,
81
- backgroundStyle: styles.sheet,
82
- onChange: onChange
83
- // enableDynamicSizing=false 关键 —— @gorhom v5 默认 true 会让 sheet 跟内容
84
- // 自动撑高忽略 snapPoints max,设 false 强制按 snapPoints 锁高度(gorhom#1783 / #918)
85
- ,
86
- enableDynamicSizing: false,
87
- enableOverDrag: false
88
- // @gorhom 默认 false:user 下拉到底部 snap 后不会关闭 sheet,只是 bounce
89
- // (BottomSheetScrollView 在 scrollOffset=0 时下拉看着像下拉刷新效果)。
90
- // 设 true 后超过最低 snap 阈值直接 dismiss → 走 onChange(-1) → onClose。
91
- ,
92
- enablePanDownToClose: true,
93
- children: /*#__PURE__*/_jsx(BottomSheetScrollView, {
94
- testID: testID,
95
- showsVerticalScrollIndicator: false,
96
- children: /*#__PURE__*/_jsx(View, {
97
- style: sheetStyle,
98
- children: children
99
- })
100
- })
101
- })
102
- });
103
- }
104
- //# sourceMappingURL=BottomSheet.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["React","useCallback","useMemo","View","GorhomBottomSheet","BottomSheetBackdrop","BottomSheetScrollView","GestureHandlerRootView","useThemedStyles","BlurLayer","makeStyles","jsx","_jsx","DEFAULT_SNAP_POINTS","BottomSheet","snapPoints","children","sheetStyle","backdrop","grabber","onClose","testID","styles","BlurBackdrop","props","appearsOnIndex","disappearsOnIndex","opacity","style","backdropTransparent","intensity","ScrimBackdrop","scrimBackdrop","renderBackdrop","undefined","onChange","index","root","backdropComponent","handleComponent","backgroundStyle","sheet","enableDynamicSizing","enableOverDrag","enablePanDownToClose","showsVerticalScrollIndicator"],"sourceRoot":"../../../../../src","sources":["components/ui/BottomSheet/BottomSheet.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,4 +0,0 @@
1
- "use strict";
2
-
3
- export { BottomSheet } from "./BottomSheet.js";
4
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["BottomSheet"],"sourceRoot":"../../../../../src","sources":["components/ui/BottomSheet/index.ts"],"mappings":";;AAAA,SAASA,WAAW,QAAQ,kBAAe","ignoreList":[]}
@@ -1,26 +0,0 @@
1
- "use strict";
2
-
3
- import { StyleSheet } from 'react-native';
4
- import { space } from "../../../theme/index.js";
5
- /** @gorhom 接管动画 / handle / scrim,这里只控 root flex + sheet bg + 顶部圆角 24
6
- * + scrim/blur backdrop 背景色(走 c.scrim token,亮 rgba(0,0,0,0.5) / 暗 0.7)。 */
7
- export const makeStyles = c => StyleSheet.create({
8
- root: {
9
- flex: 1
10
- },
11
- sheet: {
12
- backgroundColor: c.surface,
13
- borderTopLeftRadius: space['9'],
14
- borderTopRightRadius: space['9']
15
- },
16
- /** Scrim backdrop:c.scrim token,亮暗自动切换(亮 0.5 / 暗 0.7 alpha)。
17
- * 与 @gorhom 默认 backgroundColor:'black' + opacity 0.5 等价但走 token。 */
18
- scrimBackdrop: {
19
- backgroundColor: c.scrim
20
- },
21
- /** Blur backdrop:bg 透明,由 BlurLayer child 接管视觉。 */
22
- backdropTransparent: {
23
- backgroundColor: 'transparent'
24
- }
25
- });
26
- //# sourceMappingURL=styles.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["StyleSheet","space","makeStyles","c","create","root","flex","sheet","backgroundColor","surface","borderTopLeftRadius","borderTopRightRadius","scrimBackdrop","scrim","backdropTransparent"],"sourceRoot":"../../../../../src","sources":["components/ui/BottomSheet/styles.ts"],"mappings":";;AAAA,SAASA,UAAU,QAAQ,cAAc;AACzC,SAASC,KAAK,QAAQ,yBAAgB;AAGtC;AACA;AACA,OAAO,MAAMC,UAAU,GAAIC,CAAc,IACvCH,UAAU,CAACI,MAAM,CAAC;EAChBC,IAAI,EAAE;IAAEC,IAAI,EAAE;EAAE,CAAC;EACjBC,KAAK,EAAE;IACLC,eAAe,EAAEL,CAAC,CAACM,OAAO;IAC1BC,mBAAmB,EAAET,KAAK,CAAC,GAAG,CAAC;IAC/BU,oBAAoB,EAAEV,KAAK,CAAC,GAAG;EACjC,CAAC;EACD;AACJ;EACIW,aAAa,EAAE;IAAEJ,eAAe,EAAEL,CAAC,CAACU;EAAM,CAAC;EAC3C;EACAC,mBAAmB,EAAE;IAAEN,eAAe,EAAE;EAAc;AACxD,CAAC,CAAC","ignoreList":[]}
@@ -1,4 +0,0 @@
1
- "use strict";
2
-
3
- export {};
4
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sourceRoot":"../../../../../src","sources":["components/ui/BottomSheet/types.ts"],"mappings":"","ignoreList":[]}
@@ -1,4 +0,0 @@
1
- import React from 'react';
2
- import type { BottomSheetProps } from './types';
3
- export declare function BottomSheet({ snapPoints, children, sheetStyle, backdrop, grabber, onClose, testID, }: BottomSheetProps): React.JSX.Element;
4
- //# sourceMappingURL=BottomSheet.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA+B,MAAM,OAAO,CAAC;AAWpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAahD,wBAAgB,WAAW,CAAC,EAC1B,UAAgC,EAChC,QAAQ,EACR,UAAU,EACV,QAAkB,EAClB,OAAc,EACd,OAAO,EACP,MAAM,GACP,EAAE,gBAAgB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAoFtC"}
@@ -1,3 +0,0 @@
1
- export { BottomSheet } from './BottomSheet';
2
- export type { BottomSheetProps } from './types';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BottomSheet/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC"}
@@ -1,23 +0,0 @@
1
- import type { ColorTokens } from '../../../theme';
2
- /** @gorhom 接管动画 / handle / scrim,这里只控 root flex + sheet bg + 顶部圆角 24
3
- * + scrim/blur backdrop 背景色(走 c.scrim token,亮 rgba(0,0,0,0.5) / 暗 0.7)。 */
4
- export declare const makeStyles: (c: ColorTokens) => Readonly<{
5
- root: {
6
- flex: number;
7
- };
8
- sheet: {
9
- backgroundColor: string;
10
- borderTopLeftRadius: number;
11
- borderTopRightRadius: number;
12
- };
13
- /** Scrim backdrop:c.scrim token,亮暗自动切换(亮 0.5 / 暗 0.7 alpha)。
14
- * 与 @gorhom 默认 backgroundColor:'black' + opacity 0.5 等价但走 token。 */
15
- scrimBackdrop: {
16
- backgroundColor: string;
17
- };
18
- /** Blur backdrop:bg 透明,由 BlurLayer child 接管视觉。 */
19
- backdropTransparent: {
20
- backgroundColor: string;
21
- };
22
- }>;
23
- //# sourceMappingURL=styles.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BottomSheet/styles.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;4EAC4E;AAC5E,eAAO,MAAM,UAAU,GAAI,GAAG,WAAW;;;;;;;;;IAQrC;yEACqE;;;;IAErE,kDAAkD;;;;EAElD,CAAC"}
@@ -1,26 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import type { StyleProp, ViewStyle } from 'react-native';
3
- export type BottomSheetProps = {
4
- /** snap points,默认 `['30%', '60%', '95%']` 三档可拖。
5
- * 专用场景显式覆盖,如单档不可调 `['90%']`、短确认 + 中 `['40%', '85%']`。 */
6
- snapPoints?: (string | number)[];
7
- /** Sheet 内容 */
8
- children: ReactNode;
9
- /** Sheet 容器附加样式(影响 BottomSheetView style) */
10
- sheetStyle?: StyleProp<ViewStyle>;
11
- /** Backdrop 模式,默认 'scrim':
12
- * - `'scrim'`:@gorhom 默认 BottomSheetBackdrop,单色半透黑
13
- * - `'blur'`:自定义 BlurBackdrop(BlurLayer intensity='strong')
14
- * - `'none'`:无 backdrop,适合"屏 root 已有自己 backdrop"场景 */
15
- backdrop?: 'scrim' | 'blur' | 'none';
16
- /** 是否显示顶部 grabber(默认 true) */
17
- grabber?: boolean;
18
- /** Sheet 关闭(animatedIndex 收到 -1)时触发。
19
- *
20
- * **transparentModal route 模式必传 `navigation.goBack()`** —— 不然关闭 sheet 后,
21
- * 屏 route 没 pop,native overlay 屏继续覆盖,触摸全被屏吞掉。 */
22
- onClose?: () => void;
23
- /** E2E / 测试定位 */
24
- testID?: string;
25
- };
26
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/BottomSheet/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,gBAAgB,GAAG;IAC7B;8DAC0D;IAC1D,UAAU,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IACjC,eAAe;IACf,QAAQ,EAAE,SAAS,CAAC;IACpB,6CAA6C;IAC7C,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC;;;2DAGuD;IACvD,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IACrC,8BAA8B;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;sDAGkD;IAClD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC"}
@@ -1,117 +0,0 @@
1
- import React, { useCallback, useMemo } from 'react';
2
- import { View } from 'react-native';
3
- import GorhomBottomSheet, {
4
- BottomSheetBackdrop,
5
- BottomSheetScrollView,
6
- type BottomSheetBackdropProps,
7
- } from '@gorhom/bottom-sheet';
8
- import { GestureHandlerRootView } from 'react-native-gesture-handler';
9
- import { useThemedStyles } from '../../../theme';
10
- import { BlurLayer } from '../BlurLayer';
11
- import { makeStyles } from './styles';
12
- import type { BottomSheetProps } from './types';
13
-
14
- /** 底部 sheet —— @gorhom/bottom-sheet 的薄壳层。
15
- *
16
- * 适合 navigation `presentation: 'transparentModal'` 屏内 root 用法:mount 时
17
- * 默认 animateOnMount=true 从 -1 动画到 index=0,goBack() 自然关闭。
18
- * state-driven sheet 应用 @gorhom 原生 `<BottomSheetModal>`,本 wrapper 不覆盖。
19
- *
20
- * - `snapPoints` 必传(`['50%']` / `['50%', '90%']` 等)
21
- * - `backdrop` 三档:`'scrim'` / `'blur'`(BlurLayer)/ `'none'` */
22
- // 默认 30% / 60% / 95%,模块顶层 const 引用稳定。
23
- const DEFAULT_SNAP_POINTS: (string | number)[] = ['30%', '60%', '95%'];
24
-
25
- export function BottomSheet({
26
- snapPoints = DEFAULT_SNAP_POINTS,
27
- children,
28
- sheetStyle,
29
- backdrop = 'scrim',
30
- grabber = true,
31
- onClose,
32
- testID,
33
- }: BottomSheetProps): React.JSX.Element {
34
- const styles = useThemedStyles(makeStyles);
35
-
36
- /** BlurView backdrop —— 复用 @gorhom BottomSheetBackdrop 的手势 + animatedIndex
37
- * 插值,opacity=1 + bg=transparent 让 backdrop 本身不画 scrim,只画 BlurLayer。
38
- * tap-to-close + opacity 淡入 / pointer-events disable 全部继承自 @gorhom 内核。
39
- *
40
- * useCallback + styles dep 保引用稳定(主题切换时才重建),避免每次渲染新引用让
41
- * @gorhom 内部 memo 失效 / remount backdrop 树。 */
42
- const BlurBackdrop = useCallback(
43
- (props: BottomSheetBackdropProps) => (
44
- <BottomSheetBackdrop
45
- {...props}
46
- appearsOnIndex={0}
47
- disappearsOnIndex={-1}
48
- opacity={1}
49
- style={[props.style, styles.backdropTransparent]}
50
- >
51
- <BlurLayer intensity="strong" />
52
- </BottomSheetBackdrop>
53
- ),
54
- [styles.backdropTransparent]
55
- );
56
-
57
- /** Scrim backdrop —— 走 c.scrim token(亮 rgba(0,0,0,0.5) / 暗 0.7),opacity=1
58
- * 让 @gorhom 只跑透明度淡入动画,scrim 实色由 token 决定 → 暗色自动加深。 */
59
- const ScrimBackdrop = useCallback(
60
- (props: BottomSheetBackdropProps) => (
61
- <BottomSheetBackdrop
62
- {...props}
63
- appearsOnIndex={0}
64
- disappearsOnIndex={-1}
65
- opacity={1}
66
- style={[props.style, styles.scrimBackdrop]}
67
- />
68
- ),
69
- [styles.scrimBackdrop]
70
- );
71
-
72
- const renderBackdrop = useMemo(() => {
73
- switch (backdrop) {
74
- case 'none':
75
- return undefined;
76
- case 'blur':
77
- return BlurBackdrop;
78
- case 'scrim':
79
- return ScrimBackdrop;
80
- }
81
- }, [backdrop, BlurBackdrop, ScrimBackdrop]);
82
-
83
- // @gorhom onChange:index === -1 即关闭。配合 transparentModal route 必传
84
- // caller 的 onClose → navigation.goBack(),否则路由 stack 不 pop,native overlay 继续吞触摸。
85
- const onChange = (index: number) => {
86
- if (index === -1) onClose?.();
87
- };
88
-
89
- return (
90
- <GestureHandlerRootView style={styles.root}>
91
- <GorhomBottomSheet
92
- snapPoints={snapPoints}
93
- index={0}
94
- backdropComponent={renderBackdrop}
95
- handleComponent={grabber ? undefined : null}
96
- backgroundStyle={styles.sheet}
97
- onChange={onChange}
98
- // enableDynamicSizing=false 关键 —— @gorhom v5 默认 true 会让 sheet 跟内容
99
- // 自动撑高忽略 snapPoints max,设 false 强制按 snapPoints 锁高度(gorhom#1783 / #918)
100
- enableDynamicSizing={false}
101
- enableOverDrag={false}
102
- // @gorhom 默认 false:user 下拉到底部 snap 后不会关闭 sheet,只是 bounce
103
- // (BottomSheetScrollView 在 scrollOffset=0 时下拉看着像下拉刷新效果)。
104
- // 设 true 后超过最低 snap 阈值直接 dismiss → 走 onChange(-1) → onClose。
105
- enablePanDownToClose
106
- >
107
- <BottomSheetScrollView
108
- testID={testID}
109
- showsVerticalScrollIndicator={false}
110
- >
111
- {/* sheetStyle 给内层 View,ScrollView 只负责 scroll,不接管 padding / gap / maxHeight。 */}
112
- <View style={sheetStyle}>{children}</View>
113
- </BottomSheetScrollView>
114
- </GorhomBottomSheet>
115
- </GestureHandlerRootView>
116
- );
117
- }
@@ -1,2 +0,0 @@
1
- export { BottomSheet } from './BottomSheet';
2
- export type { BottomSheetProps } from './types';
@@ -1,20 +0,0 @@
1
- import { StyleSheet } from 'react-native';
2
- import { space } from '../../../theme';
3
- import type { ColorTokens } from '../../../theme';
4
-
5
- /** @gorhom 接管动画 / handle / scrim,这里只控 root flex + sheet bg + 顶部圆角 24
6
- * + scrim/blur backdrop 背景色(走 c.scrim token,亮 rgba(0,0,0,0.5) / 暗 0.7)。 */
7
- export const makeStyles = (c: ColorTokens) =>
8
- StyleSheet.create({
9
- root: { flex: 1 },
10
- sheet: {
11
- backgroundColor: c.surface,
12
- borderTopLeftRadius: space['9'],
13
- borderTopRightRadius: space['9'],
14
- },
15
- /** Scrim backdrop:c.scrim token,亮暗自动切换(亮 0.5 / 暗 0.7 alpha)。
16
- * 与 @gorhom 默认 backgroundColor:'black' + opacity 0.5 等价但走 token。 */
17
- scrimBackdrop: { backgroundColor: c.scrim },
18
- /** Blur backdrop:bg 透明,由 BlurLayer child 接管视觉。 */
19
- backdropTransparent: { backgroundColor: 'transparent' },
20
- });
@@ -1,26 +0,0 @@
1
- import type { ReactNode } from 'react';
2
- import type { StyleProp, ViewStyle } from 'react-native';
3
-
4
- export type BottomSheetProps = {
5
- /** snap points,默认 `['30%', '60%', '95%']` 三档可拖。
6
- * 专用场景显式覆盖,如单档不可调 `['90%']`、短确认 + 中 `['40%', '85%']`。 */
7
- snapPoints?: (string | number)[];
8
- /** Sheet 内容 */
9
- children: ReactNode;
10
- /** Sheet 容器附加样式(影响 BottomSheetView style) */
11
- sheetStyle?: StyleProp<ViewStyle>;
12
- /** Backdrop 模式,默认 'scrim':
13
- * - `'scrim'`:@gorhom 默认 BottomSheetBackdrop,单色半透黑
14
- * - `'blur'`:自定义 BlurBackdrop(BlurLayer intensity='strong')
15
- * - `'none'`:无 backdrop,适合"屏 root 已有自己 backdrop"场景 */
16
- backdrop?: 'scrim' | 'blur' | 'none';
17
- /** 是否显示顶部 grabber(默认 true) */
18
- grabber?: boolean;
19
- /** Sheet 关闭(animatedIndex 收到 -1)时触发。
20
- *
21
- * **transparentModal route 模式必传 `navigation.goBack()`** —— 不然关闭 sheet 后,
22
- * 屏 route 没 pop,native overlay 屏继续覆盖,触摸全被屏吞掉。 */
23
- onClose?: () => void;
24
- /** E2E / 测试定位 */
25
- testID?: string;
26
- };