@unif/react-native-design 0.5.1 → 0.6.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.
- package/README.md +60 -10
- package/lib/module/components/ui/Toast/ToastHost.js +23 -3
- package/lib/module/components/ui/Toast/ToastHost.js.map +1 -1
- package/lib/module/components/ui/Toast/styles.js +1 -1
- package/lib/module/components/ui/Toast/styles.js.map +1 -1
- package/lib/module/components/ui/Toast/toast.js +4 -2
- package/lib/module/components/ui/Toast/toast.js.map +1 -1
- package/lib/module/components/ui/index.js +0 -2
- package/lib/module/components/ui/index.js.map +1 -1
- package/lib/typescript/src/components/ui/Input/Input.d.ts +3 -3
- package/lib/typescript/src/components/ui/Search/Search.d.ts +3 -3
- package/lib/typescript/src/components/ui/TextField/TextFieldBase.d.ts +3 -3
- package/lib/typescript/src/components/ui/Textarea/Textarea.d.ts +3 -3
- package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts +3 -0
- package/lib/typescript/src/components/ui/Toast/ToastHost.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/index.d.ts +1 -1
- package/lib/typescript/src/components/ui/Toast/index.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/styles.d.ts +0 -1
- package/lib/typescript/src/components/ui/Toast/styles.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/toast.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Toast/types.d.ts +9 -3
- package/lib/typescript/src/components/ui/Toast/types.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/index.d.ts +1 -5
- package/lib/typescript/src/components/ui/index.d.ts.map +1 -1
- package/package.json +6 -3
- package/src/components/ui/Toast/ToastHost.tsx +20 -3
- package/src/components/ui/Toast/index.ts +1 -0
- package/src/components/ui/Toast/styles.ts +1 -1
- package/src/components/ui/Toast/toast.ts +2 -1
- package/src/components/ui/Toast/types.ts +10 -3
- package/src/components/ui/index.ts +1 -4
- package/lib/module/components/ui/BottomSheet/BottomSheet.js +0 -104
- package/lib/module/components/ui/BottomSheet/BottomSheet.js.map +0 -1
- package/lib/module/components/ui/BottomSheet/index.js +0 -4
- package/lib/module/components/ui/BottomSheet/index.js.map +0 -1
- package/lib/module/components/ui/BottomSheet/styles.js +0 -26
- package/lib/module/components/ui/BottomSheet/styles.js.map +0 -1
- package/lib/module/components/ui/BottomSheet/types.js +0 -4
- package/lib/module/components/ui/BottomSheet/types.js.map +0 -1
- package/lib/module/components/ui/Confirm/ConfirmHost.js +0 -111
- package/lib/module/components/ui/Confirm/ConfirmHost.js.map +0 -1
- package/lib/module/components/ui/Confirm/confirm.js +0 -51
- package/lib/module/components/ui/Confirm/confirm.js.map +0 -1
- package/lib/module/components/ui/Confirm/index.js +0 -5
- package/lib/module/components/ui/Confirm/index.js.map +0 -1
- package/lib/module/components/ui/Confirm/styles.js +0 -35
- package/lib/module/components/ui/Confirm/styles.js.map +0 -1
- package/lib/module/components/ui/Confirm/types.js +0 -2
- package/lib/module/components/ui/Confirm/types.js.map +0 -1
- package/lib/typescript/src/components/ui/BottomSheet/BottomSheet.d.ts +0 -4
- package/lib/typescript/src/components/ui/BottomSheet/BottomSheet.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/BottomSheet/index.d.ts +0 -3
- package/lib/typescript/src/components/ui/BottomSheet/index.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/BottomSheet/styles.d.ts +0 -23
- package/lib/typescript/src/components/ui/BottomSheet/styles.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/BottomSheet/types.d.ts +0 -26
- package/lib/typescript/src/components/ui/BottomSheet/types.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts +0 -9
- package/lib/typescript/src/components/ui/Confirm/ConfirmHost.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/Confirm/confirm.d.ts +0 -20
- package/lib/typescript/src/components/ui/Confirm/confirm.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/Confirm/index.d.ts +0 -4
- package/lib/typescript/src/components/ui/Confirm/index.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/Confirm/styles.d.ts +0 -32
- package/lib/typescript/src/components/ui/Confirm/styles.d.ts.map +0 -1
- package/lib/typescript/src/components/ui/Confirm/types.d.ts +0 -21
- package/lib/typescript/src/components/ui/Confirm/types.d.ts.map +0 -1
- package/src/components/ui/BottomSheet/BottomSheet.tsx +0 -117
- package/src/components/ui/BottomSheet/index.ts +0 -2
- package/src/components/ui/BottomSheet/styles.ts +0 -20
- package/src/components/ui/BottomSheet/types.ts +0 -26
- package/src/components/ui/Confirm/ConfirmHost.tsx +0 -134
- package/src/components/ui/Confirm/confirm.ts +0 -53
- package/src/components/ui/Confirm/index.ts +0 -3
- package/src/components/ui/Confirm/styles.ts +0 -35
- package/src/components/ui/Confirm/types.ts +0 -22
|
@@ -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,9 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
/**
|
|
3
|
-
* Confirm 对话框 Portal —— App 根挂一次,监听 `confirm()` 调用并渲染。
|
|
4
|
-
*
|
|
5
|
-
* 走 `<BottomSheetModal>` + `<BottomSheetModalProvider>`,通过 Provider Portal
|
|
6
|
-
* 自动渲染到 App 顶层 —— 整屏 backdrop + 不受 React tree 位置影响。
|
|
7
|
-
*/
|
|
8
|
-
export declare function ConfirmHost(): React.JSX.Element | null;
|
|
9
|
-
//# sourceMappingURL=ConfirmHost.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ConfirmHost.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Confirm/ConfirmHost.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAC;AA4Bf;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CA6FtD"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { ConfirmOptions, Subscriber } from './types';
|
|
2
|
-
export declare const _subs: Set<Subscriber>;
|
|
3
|
-
/**
|
|
4
|
-
* 弹出确认对话框,返回 Promise<boolean>。
|
|
5
|
-
* - 用户点确认 → resolve(true)
|
|
6
|
-
* - 用户点取消 / 点 backdrop / 拖关闭 → resolve(false)
|
|
7
|
-
*
|
|
8
|
-
* 示例:
|
|
9
|
-
* ```ts
|
|
10
|
-
* const ok = await confirm({
|
|
11
|
-
* title: '确认注销账号?',
|
|
12
|
-
* message: '注销后所有数据删除,无法恢复',
|
|
13
|
-
* confirmLabel: '确认注销',
|
|
14
|
-
* destructive: true,
|
|
15
|
-
* });
|
|
16
|
-
* if (ok) doLogout();
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
export declare function confirm(options: ConfirmOptions): Promise<boolean>;
|
|
20
|
-
//# sourceMappingURL=confirm.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"confirm.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Confirm/confirm.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAgB,UAAU,EAAE,MAAM,SAAS,CAAC;AAMxE,eAAO,MAAM,KAAK,iBAAwB,CAAC;AAE3C;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAmBjE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Confirm/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { ColorTokens } from '../../../theme';
|
|
2
|
-
/** Confirm 对话框 styles —— title/message 走 BottomSheetView 顶部段,
|
|
3
|
-
* actions 走 BottomSheetFooter 自动浮到 sheet 底部。 */
|
|
4
|
-
export declare const makeStyles: (c: ColorTokens) => Readonly<{
|
|
5
|
-
sheetBackground: {
|
|
6
|
-
backgroundColor: string;
|
|
7
|
-
};
|
|
8
|
-
sheet: {
|
|
9
|
-
paddingHorizontal: number;
|
|
10
|
-
paddingTop: number;
|
|
11
|
-
gap: number;
|
|
12
|
-
};
|
|
13
|
-
title: {
|
|
14
|
-
fontSize: number;
|
|
15
|
-
fontWeight: "600";
|
|
16
|
-
color: string;
|
|
17
|
-
letterSpacing: number;
|
|
18
|
-
};
|
|
19
|
-
message: {
|
|
20
|
-
fontSize: number;
|
|
21
|
-
color: string;
|
|
22
|
-
lineHeight: number;
|
|
23
|
-
};
|
|
24
|
-
actions: {
|
|
25
|
-
flexDirection: "row";
|
|
26
|
-
gap: number;
|
|
27
|
-
paddingHorizontal: number;
|
|
28
|
-
paddingTop: number;
|
|
29
|
-
paddingBottom: number;
|
|
30
|
-
};
|
|
31
|
-
}>;
|
|
32
|
-
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Confirm/styles.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD;iDACiD;AACjD,eAAO,MAAM,UAAU,GAAI,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BrC,CAAC"}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/** Confirm 入参。 */
|
|
2
|
-
export type ConfirmOptions = {
|
|
3
|
-
/** 主标题 —— 短且明确,如 "确认注销账号?" */
|
|
4
|
-
title: string;
|
|
5
|
-
/** 说明文本 —— 1-2 句解释操作后果。可选 */
|
|
6
|
-
message?: string;
|
|
7
|
-
/** 确认按钮文案,默认 "确认" */
|
|
8
|
-
confirmLabel?: string;
|
|
9
|
-
/** 取消按钮文案,默认 "取消" */
|
|
10
|
-
cancelLabel?: string;
|
|
11
|
-
/** 标记为破坏性操作 —— 确认按钮变红(c.error),用于"删除 / 注销 / 取消订单" */
|
|
12
|
-
destructive?: boolean;
|
|
13
|
-
};
|
|
14
|
-
/** Host 内部 entry —— options + resolve 回调,用户点 确认/取消/backdrop 时 resolve。 */
|
|
15
|
-
export type ConfirmEntry = ConfirmOptions & {
|
|
16
|
-
id: number;
|
|
17
|
-
resolve: (confirmed: boolean) => void;
|
|
18
|
-
};
|
|
19
|
-
/** ConfirmHost 监听器签名 —— 收到 entry 渲染对话框;收到 null 表示关闭。 */
|
|
20
|
-
export type Subscriber = (entry: ConfirmEntry | null) => void;
|
|
21
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/components/ui/Confirm/types.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAAG;IAC3B,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qBAAqB;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,0EAA0E;AAC1E,MAAM,MAAM,YAAY,GAAG,cAAc,GAAG;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,wDAAwD;AACxD,MAAM,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,KAAK,IAAI,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,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
|
-
};
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
useCallback,
|
|
3
|
-
useEffect,
|
|
4
|
-
useMemo,
|
|
5
|
-
useRef,
|
|
6
|
-
useState,
|
|
7
|
-
} from 'react';
|
|
8
|
-
import { Text, View } from 'react-native';
|
|
9
|
-
import {
|
|
10
|
-
BottomSheetBackdrop,
|
|
11
|
-
BottomSheetFooter,
|
|
12
|
-
BottomSheetModal,
|
|
13
|
-
BottomSheetView,
|
|
14
|
-
type BottomSheetBackdropProps,
|
|
15
|
-
type BottomSheetFooterProps,
|
|
16
|
-
} from '@gorhom/bottom-sheet';
|
|
17
|
-
import { useThemedStyles } from '../../../theme';
|
|
18
|
-
import { Button } from '../Button';
|
|
19
|
-
import { _subs } from './confirm';
|
|
20
|
-
import { makeStyles } from './styles';
|
|
21
|
-
import type { ConfirmEntry, Subscriber } from './types';
|
|
22
|
-
|
|
23
|
-
/** Scrim backdrop —— 单色半透黑 opacity 0.5 */
|
|
24
|
-
function ScrimBackdrop(props: BottomSheetBackdropProps) {
|
|
25
|
-
return (
|
|
26
|
-
<BottomSheetBackdrop
|
|
27
|
-
{...props}
|
|
28
|
-
appearsOnIndex={0}
|
|
29
|
-
disappearsOnIndex={-1}
|
|
30
|
-
opacity={0.5}
|
|
31
|
-
/>
|
|
32
|
-
);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Confirm 对话框 Portal —— App 根挂一次,监听 `confirm()` 调用并渲染。
|
|
37
|
-
*
|
|
38
|
-
* 走 `<BottomSheetModal>` + `<BottomSheetModalProvider>`,通过 Provider Portal
|
|
39
|
-
* 自动渲染到 App 顶层 —— 整屏 backdrop + 不受 React tree 位置影响。
|
|
40
|
-
*/
|
|
41
|
-
export function ConfirmHost(): React.JSX.Element | null {
|
|
42
|
-
const styles = useThemedStyles(makeStyles);
|
|
43
|
-
const modalRef = useRef<BottomSheetModal>(null);
|
|
44
|
-
const [entry, setEntry] = useState<ConfirmEntry | null>(null);
|
|
45
|
-
|
|
46
|
-
useEffect(() => {
|
|
47
|
-
const sub: Subscriber = (next) => {
|
|
48
|
-
setEntry(next);
|
|
49
|
-
if (next) {
|
|
50
|
-
modalRef.current?.present();
|
|
51
|
-
} else {
|
|
52
|
-
modalRef.current?.dismiss();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
_subs.add(sub);
|
|
56
|
-
return () => {
|
|
57
|
-
_subs.delete(sub);
|
|
58
|
-
};
|
|
59
|
-
}, []);
|
|
60
|
-
|
|
61
|
-
// onDismiss:drag-to-close / backdrop tap / 程序 dismiss 都触发,entry 还在视为取消
|
|
62
|
-
// 三个 handler 都用 useCallback + [entry] deps —— 让 renderFooter 的 useCallback
|
|
63
|
-
// deps 能正确锁定它们,引用稳定 = @gorhom 不会因 backdrop 重生成而抖动。
|
|
64
|
-
const handleDismiss = useCallback(() => {
|
|
65
|
-
if (entry) {
|
|
66
|
-
entry.resolve(false);
|
|
67
|
-
setEntry(null);
|
|
68
|
-
}
|
|
69
|
-
}, [entry]);
|
|
70
|
-
|
|
71
|
-
const handleConfirm = useCallback(() => {
|
|
72
|
-
entry?.resolve(true);
|
|
73
|
-
modalRef.current?.dismiss();
|
|
74
|
-
}, [entry]);
|
|
75
|
-
|
|
76
|
-
const handleCancel = useCallback(() => {
|
|
77
|
-
entry?.resolve(false);
|
|
78
|
-
modalRef.current?.dismiss();
|
|
79
|
-
}, [entry]);
|
|
80
|
-
|
|
81
|
-
const snapPoints = useMemo(() => ['30%'], []);
|
|
82
|
-
|
|
83
|
-
// 用 BottomSheetFooter 浮按钮:BottomSheetView 内部 absolute top/left/right 无 bottom,
|
|
84
|
-
// flex marginTop:auto 推不动按钮,所以必须走 footer + bottomInset 自动避让键盘。
|
|
85
|
-
const renderFooter = useCallback(
|
|
86
|
-
(props: BottomSheetFooterProps) =>
|
|
87
|
-
entry ? (
|
|
88
|
-
<BottomSheetFooter {...props} bottomInset={0}>
|
|
89
|
-
<View style={styles.actions}>
|
|
90
|
-
<Button
|
|
91
|
-
testID="confirm-cancel"
|
|
92
|
-
label={entry.cancelLabel ?? '取消'}
|
|
93
|
-
variant="secondary"
|
|
94
|
-
block
|
|
95
|
-
onPress={handleCancel}
|
|
96
|
-
/>
|
|
97
|
-
<Button
|
|
98
|
-
testID="confirm-ok"
|
|
99
|
-
label={entry.confirmLabel ?? '确认'}
|
|
100
|
-
variant={entry.destructive ? 'danger' : 'primary'}
|
|
101
|
-
block
|
|
102
|
-
onPress={handleConfirm}
|
|
103
|
-
/>
|
|
104
|
-
</View>
|
|
105
|
-
</BottomSheetFooter>
|
|
106
|
-
) : null,
|
|
107
|
-
[entry, styles.actions, handleCancel, handleConfirm]
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<BottomSheetModal
|
|
112
|
-
ref={modalRef}
|
|
113
|
-
snapPoints={snapPoints}
|
|
114
|
-
index={0}
|
|
115
|
-
enableDynamicSizing={false}
|
|
116
|
-
enableOverDrag={false}
|
|
117
|
-
backdropComponent={ScrimBackdrop}
|
|
118
|
-
backgroundStyle={styles.sheetBackground}
|
|
119
|
-
footerComponent={renderFooter}
|
|
120
|
-
onDismiss={handleDismiss}
|
|
121
|
-
>
|
|
122
|
-
<BottomSheetView style={styles.sheet}>
|
|
123
|
-
{entry ? (
|
|
124
|
-
<>
|
|
125
|
-
<Text style={styles.title}>{entry.title}</Text>
|
|
126
|
-
{entry.message ? (
|
|
127
|
-
<Text style={styles.message}>{entry.message}</Text>
|
|
128
|
-
) : null}
|
|
129
|
-
</>
|
|
130
|
-
) : null}
|
|
131
|
-
</BottomSheetView>
|
|
132
|
-
</BottomSheetModal>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 命令式 `confirm()` API —— 跟 `<ConfirmHost />` 配对使用。
|
|
3
|
-
*
|
|
4
|
-
* 业务任意位置 `const ok = await confirm({title, message, ...})`,
|
|
5
|
-
* 不用维护 useState / open / onClose。
|
|
6
|
-
*
|
|
7
|
-
* 同一时间只允许 1 个 confirm 活跃;若已有正在显示,新请求立即 resolve(false) 并 warn。
|
|
8
|
-
*/
|
|
9
|
-
import { createLogger } from '../../../utils/logger';
|
|
10
|
-
import type { ConfirmOptions, ConfirmEntry, Subscriber } from './types';
|
|
11
|
-
|
|
12
|
-
const log = createLogger('confirm');
|
|
13
|
-
|
|
14
|
-
let _id = 0;
|
|
15
|
-
let _activeEntry: ConfirmEntry | null = null;
|
|
16
|
-
export const _subs = new Set<Subscriber>();
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* 弹出确认对话框,返回 Promise<boolean>。
|
|
20
|
-
* - 用户点确认 → resolve(true)
|
|
21
|
-
* - 用户点取消 / 点 backdrop / 拖关闭 → resolve(false)
|
|
22
|
-
*
|
|
23
|
-
* 示例:
|
|
24
|
-
* ```ts
|
|
25
|
-
* const ok = await confirm({
|
|
26
|
-
* title: '确认注销账号?',
|
|
27
|
-
* message: '注销后所有数据删除,无法恢复',
|
|
28
|
-
* confirmLabel: '确认注销',
|
|
29
|
-
* destructive: true,
|
|
30
|
-
* });
|
|
31
|
-
* if (ok) doLogout();
|
|
32
|
-
* ```
|
|
33
|
-
*/
|
|
34
|
-
export function confirm(options: ConfirmOptions): Promise<boolean> {
|
|
35
|
-
if (_activeEntry) {
|
|
36
|
-
log.warn(
|
|
37
|
-
'confirm() 已有一个对话框在显示,新请求被拒绝(同一时间只 1 个,避免叠加)。'
|
|
38
|
-
);
|
|
39
|
-
return Promise.resolve(false);
|
|
40
|
-
}
|
|
41
|
-
return new Promise<boolean>((resolve) => {
|
|
42
|
-
const entry: ConfirmEntry = {
|
|
43
|
-
id: ++_id,
|
|
44
|
-
...options,
|
|
45
|
-
resolve: (confirmed: boolean) => {
|
|
46
|
-
_activeEntry = null;
|
|
47
|
-
resolve(confirmed);
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
_activeEntry = entry;
|
|
51
|
-
_subs.forEach((s) => s(entry));
|
|
52
|
-
});
|
|
53
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { StyleSheet } from 'react-native';
|
|
2
|
-
import { fw, space, type as t } from '../../../theme';
|
|
3
|
-
import type { ColorTokens } from '../../../theme';
|
|
4
|
-
|
|
5
|
-
/** Confirm 对话框 styles —— title/message 走 BottomSheetView 顶部段,
|
|
6
|
-
* actions 走 BottomSheetFooter 自动浮到 sheet 底部。 */
|
|
7
|
-
export const makeStyles = (c: ColorTokens) =>
|
|
8
|
-
StyleSheet.create({
|
|
9
|
-
sheetBackground: {
|
|
10
|
-
backgroundColor: c.surface,
|
|
11
|
-
},
|
|
12
|
-
sheet: {
|
|
13
|
-
paddingHorizontal: space['9'],
|
|
14
|
-
paddingTop: space['4'],
|
|
15
|
-
gap: space['5'],
|
|
16
|
-
},
|
|
17
|
-
title: {
|
|
18
|
-
fontSize: t.heroSm,
|
|
19
|
-
fontWeight: fw.semi,
|
|
20
|
-
color: c.foreground,
|
|
21
|
-
letterSpacing: -0.2,
|
|
22
|
-
},
|
|
23
|
-
message: {
|
|
24
|
-
fontSize: t.body,
|
|
25
|
-
color: c.foregroundMuted,
|
|
26
|
-
lineHeight: t.body * 1.45,
|
|
27
|
-
},
|
|
28
|
-
actions: {
|
|
29
|
-
flexDirection: 'row',
|
|
30
|
-
gap: space['4'],
|
|
31
|
-
paddingHorizontal: space['9'],
|
|
32
|
-
paddingTop: space['5'],
|
|
33
|
-
paddingBottom: space['7'],
|
|
34
|
-
},
|
|
35
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/** Confirm 入参。 */
|
|
2
|
-
export type ConfirmOptions = {
|
|
3
|
-
/** 主标题 —— 短且明确,如 "确认注销账号?" */
|
|
4
|
-
title: string;
|
|
5
|
-
/** 说明文本 —— 1-2 句解释操作后果。可选 */
|
|
6
|
-
message?: string;
|
|
7
|
-
/** 确认按钮文案,默认 "确认" */
|
|
8
|
-
confirmLabel?: string;
|
|
9
|
-
/** 取消按钮文案,默认 "取消" */
|
|
10
|
-
cancelLabel?: string;
|
|
11
|
-
/** 标记为破坏性操作 —— 确认按钮变红(c.error),用于"删除 / 注销 / 取消订单" */
|
|
12
|
-
destructive?: boolean;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/** Host 内部 entry —— options + resolve 回调,用户点 确认/取消/backdrop 时 resolve。 */
|
|
16
|
-
export type ConfirmEntry = ConfirmOptions & {
|
|
17
|
-
id: number;
|
|
18
|
-
resolve: (confirmed: boolean) => void;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/** ConfirmHost 监听器签名 —— 收到 entry 渲染对话框;收到 null 表示关闭。 */
|
|
22
|
-
export type Subscriber = (entry: ConfirmEntry | null) => void;
|