zkit-ui 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.
- package/README.md +267 -0
- package/dist/ComponentLibProvider.d.ts +15 -0
- package/dist/ComponentLibProvider.d.ts.map +1 -0
- package/dist/ComponentLibProvider.js +18 -0
- package/dist/assets/animations/spinner.json +1 -0
- package/dist/assets/icons/check.svg +4 -0
- package/dist/assets/icons/toast/error.webp +0 -0
- package/dist/assets/icons/toast/success.webp +0 -0
- package/dist/assets/icons/toast/warning.webp +0 -0
- package/dist/config.d.ts +16 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +42 -0
- package/dist/i18n/I18nProvider.d.ts +11 -0
- package/dist/i18n/I18nProvider.d.ts.map +1 -0
- package/dist/i18n/I18nProvider.js +84 -0
- package/dist/i18n/locale.d.ts +7 -0
- package/dist/i18n/locale.d.ts.map +1 -0
- package/dist/i18n/locale.js +87 -0
- package/dist/i18n/locales/de.d.ts +51 -0
- package/dist/i18n/locales/de.d.ts.map +1 -0
- package/dist/i18n/locales/de.js +62 -0
- package/dist/i18n/locales/en-US.d.ts +51 -0
- package/dist/i18n/locales/en-US.d.ts.map +1 -0
- package/dist/i18n/locales/en-US.js +62 -0
- package/dist/i18n/locales/index.d.ts +9 -0
- package/dist/i18n/locales/index.d.ts.map +1 -0
- package/dist/i18n/locales/index.js +23 -0
- package/dist/i18n/locales/ja.d.ts +51 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -0
- package/dist/i18n/locales/ja.js +62 -0
- package/dist/i18n/locales/zh-CN.d.ts +51 -0
- package/dist/i18n/locales/zh-CN.d.ts.map +1 -0
- package/dist/i18n/locales/zh-CN.js +62 -0
- package/dist/i18n/locales/zh-TW.d.ts +51 -0
- package/dist/i18n/locales/zh-TW.d.ts.map +1 -0
- package/dist/i18n/locales/zh-TW.js +62 -0
- package/dist/i18n/types.d.ts +11 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/types.js +2 -0
- package/dist/i18n/useI18n.d.ts +2 -0
- package/dist/i18n/useI18n.d.ts.map +1 -0
- package/dist/i18n/useI18n.js +41 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +90 -0
- package/dist/services/ActionDialogService/ActionDialog.d.ts +4 -0
- package/dist/services/ActionDialogService/ActionDialog.d.ts.map +1 -0
- package/dist/services/ActionDialogService/ActionDialog.js +531 -0
- package/dist/services/ActionDialogService/index.d.ts +4 -0
- package/dist/services/ActionDialogService/index.d.ts.map +1 -0
- package/dist/services/ActionDialogService/index.js +8 -0
- package/dist/services/ActionDialogService/service.d.ts +7 -0
- package/dist/services/ActionDialogService/service.d.ts.map +1 -0
- package/dist/services/ActionDialogService/service.js +309 -0
- package/dist/services/ActionDialogService/shared.d.ts +17 -0
- package/dist/services/ActionDialogService/shared.d.ts.map +1 -0
- package/dist/services/ActionDialogService/shared.js +167 -0
- package/dist/services/ActionDialogService/types.d.ts +160 -0
- package/dist/services/ActionDialogService/types.d.ts.map +1 -0
- package/dist/services/ActionDialogService/types.js +2 -0
- package/dist/services/CardToastService/index.d.ts +115 -0
- package/dist/services/CardToastService/index.d.ts.map +1 -0
- package/dist/services/CardToastService/index.js +899 -0
- package/dist/services/ImagePreviewService/index.d.ts +179 -0
- package/dist/services/ImagePreviewService/index.d.ts.map +1 -0
- package/dist/services/ImagePreviewService/index.js +1383 -0
- package/dist/services/LoadingService/index.d.ts +146 -0
- package/dist/services/LoadingService/index.d.ts.map +1 -0
- package/dist/services/LoadingService/index.js +827 -0
- package/dist/services/PermissionPurposeDialogService/index.d.ts +99 -0
- package/dist/services/PermissionPurposeDialogService/index.d.ts.map +1 -0
- package/dist/services/PermissionPurposeDialogService/index.js +360 -0
- package/dist/services/PickerService/index.d.ts +128 -0
- package/dist/services/PickerService/index.d.ts.map +1 -0
- package/dist/services/PickerService/index.js +250 -0
- package/dist/theme/ThemeProvider.d.ts +15 -0
- package/dist/theme/ThemeProvider.d.ts.map +1 -0
- package/dist/theme/ThemeProvider.js +61 -0
- package/dist/theme/defaultTheme.d.ts +3 -0
- package/dist/theme/defaultTheme.d.ts.map +1 -0
- package/dist/theme/defaultTheme.js +28 -0
- package/dist/theme/mergeTheme.d.ts +3 -0
- package/dist/theme/mergeTheme.d.ts.map +1 -0
- package/dist/theme/mergeTheme.js +19 -0
- package/dist/theme/types.d.ts +17 -0
- package/dist/theme/types.d.ts.map +1 -0
- package/dist/theme/types.js +2 -0
- package/dist/theme/useTheme.d.ts +2 -0
- package/dist/theme/useTheme.d.ts.map +1 -0
- package/dist/theme/useTheme.js +46 -0
- package/dist/ui/Accordion/index.d.ts +99 -0
- package/dist/ui/Accordion/index.d.ts.map +1 -0
- package/dist/ui/Accordion/index.js +777 -0
- package/dist/ui/AddressCascader/index.d.ts +58 -0
- package/dist/ui/AddressCascader/index.d.ts.map +1 -0
- package/dist/ui/AddressCascader/index.js +710 -0
- package/dist/ui/BetweenTime/index.d.ts +82 -0
- package/dist/ui/BetweenTime/index.d.ts.map +1 -0
- package/dist/ui/BetweenTime/index.js +702 -0
- package/dist/ui/Button/index.d.ts +93 -0
- package/dist/ui/Button/index.d.ts.map +1 -0
- package/dist/ui/Button/index.js +832 -0
- package/dist/ui/Checkbox/index.d.ts +103 -0
- package/dist/ui/Checkbox/index.d.ts.map +1 -0
- package/dist/ui/Checkbox/index.js +694 -0
- package/dist/ui/DatePicker/index.d.ts +5 -0
- package/dist/ui/DatePicker/index.d.ts.map +1 -0
- package/dist/ui/DatePicker/index.js +157 -0
- package/dist/ui/DatePicker/types.d.ts +99 -0
- package/dist/ui/DatePicker/types.d.ts.map +1 -0
- package/dist/ui/DatePicker/types.js +2 -0
- package/dist/ui/DatePicker/utils.d.ts +32 -0
- package/dist/ui/DatePicker/utils.d.ts.map +1 -0
- package/dist/ui/DatePicker/utils.js +316 -0
- package/dist/ui/LinkedScroll/index.d.ts +78 -0
- package/dist/ui/LinkedScroll/index.d.ts.map +1 -0
- package/dist/ui/LinkedScroll/index.js +470 -0
- package/dist/ui/LoadingSpinner/index.d.ts +8 -0
- package/dist/ui/LoadingSpinner/index.d.ts.map +1 -0
- package/dist/ui/LoadingSpinner/index.js +122 -0
- package/dist/ui/Picker/actionBar.d.ts +14 -0
- package/dist/ui/Picker/actionBar.d.ts.map +1 -0
- package/dist/ui/Picker/actionBar.js +28 -0
- package/dist/ui/Picker/index.d.ts +5 -0
- package/dist/ui/Picker/index.d.ts.map +1 -0
- package/dist/ui/Picker/index.js +412 -0
- package/dist/ui/Picker/types.d.ts +80 -0
- package/dist/ui/Picker/types.d.ts.map +1 -0
- package/dist/ui/Picker/types.js +2 -0
- package/dist/ui/Picker/utils.d.ts +27 -0
- package/dist/ui/Picker/utils.d.ts.map +1 -0
- package/dist/ui/Picker/utils.js +182 -0
- package/dist/ui/Radio/index.d.ts +95 -0
- package/dist/ui/Radio/index.d.ts.map +1 -0
- package/dist/ui/Radio/index.js +633 -0
- package/dist/ui/Sheet/index.d.ts +12 -0
- package/dist/ui/Sheet/index.d.ts.map +1 -0
- package/dist/ui/Sheet/index.js +832 -0
- package/dist/ui/Sheet/nativeBottom.d.ts +52 -0
- package/dist/ui/Sheet/nativeBottom.d.ts.map +1 -0
- package/dist/ui/Sheet/nativeBottom.js +442 -0
- package/dist/ui/Sheet/nativeBottom.web.d.ts +18 -0
- package/dist/ui/Sheet/nativeBottom.web.d.ts.map +1 -0
- package/dist/ui/Sheet/nativeBottom.web.js +46 -0
- package/dist/ui/Sheet/slots.d.ts +5 -0
- package/dist/ui/Sheet/slots.d.ts.map +1 -0
- package/dist/ui/Sheet/slots.js +40 -0
- package/dist/ui/Sheet/types.d.ts +131 -0
- package/dist/ui/Sheet/types.d.ts.map +1 -0
- package/dist/ui/Sheet/types.js +2 -0
- package/dist/ui/SliderCaptcha/index.d.ts +57 -0
- package/dist/ui/SliderCaptcha/index.d.ts.map +1 -0
- package/dist/ui/SliderCaptcha/index.js +586 -0
- package/dist/ui/Switch/index.d.ts +72 -0
- package/dist/ui/Switch/index.d.ts.map +1 -0
- package/dist/ui/Switch/index.js +671 -0
- package/dist/ui/Text/index.d.ts +41 -0
- package/dist/ui/Text/index.d.ts.map +1 -0
- package/dist/ui/Text/index.js +325 -0
- package/dist/ui/TextInput/TextInputPrimitive.d.ts +8 -0
- package/dist/ui/TextInput/TextInputPrimitive.d.ts.map +1 -0
- package/dist/ui/TextInput/TextInputPrimitive.js +54 -0
- package/dist/ui/TextInput/index.d.ts +89 -0
- package/dist/ui/TextInput/index.d.ts.map +1 -0
- package/dist/ui/TextInput/index.js +545 -0
- package/dist/ui/WheelColumn/ZKitWheelPickerNativeComponent.d.ts +39 -0
- package/dist/ui/WheelColumn/ZKitWheelPickerNativeComponent.d.ts.map +1 -0
- package/dist/ui/WheelColumn/ZKitWheelPickerNativeComponent.js +60 -0
- package/dist/ui/WheelColumn/constants.d.ts +2 -0
- package/dist/ui/WheelColumn/constants.d.ts.map +1 -0
- package/dist/ui/WheelColumn/constants.js +4 -0
- package/dist/ui/WheelColumn/index.d.ts +59 -0
- package/dist/ui/WheelColumn/index.d.ts.map +1 -0
- package/dist/ui/WheelColumn/index.js +547 -0
- package/ios/ZKitWheelPicker.h +18 -0
- package/ios/ZKitWheelPicker.mm +230 -0
- package/ios/ZKitWheelPickerLabel.h +10 -0
- package/ios/ZKitWheelPickerLabel.mm +31 -0
- package/ios/ZKitWheelPickerManager.h +5 -0
- package/ios/ZKitWheelPickerManager.mm +53 -0
- package/package.json +75 -0
- package/react-native.config.js +10 -0
- package/src/ComponentLibProvider.tsx +56 -0
- package/src/assets/animations/spinner.json +1 -0
- package/src/assets/icons/check.svg +4 -0
- package/src/assets/icons/toast/error.webp +0 -0
- package/src/assets/icons/toast/success.webp +0 -0
- package/src/assets/icons/toast/warning.webp +0 -0
- package/src/config.ts +65 -0
- package/src/i18n/I18nProvider.tsx +69 -0
- package/src/i18n/locale.ts +108 -0
- package/src/i18n/locales/de.ts +67 -0
- package/src/i18n/locales/en-US.ts +67 -0
- package/src/i18n/locales/index.ts +19 -0
- package/src/i18n/locales/ja.ts +67 -0
- package/src/i18n/locales/zh-CN.ts +67 -0
- package/src/i18n/locales/zh-TW.ts +67 -0
- package/src/i18n/types.ts +21 -0
- package/src/i18n/useI18n.ts +7 -0
- package/src/index.ts +395 -0
- package/src/services/ActionDialogService/ActionDialog.tsx +756 -0
- package/src/services/ActionDialogService/README.md +146 -0
- package/src/services/ActionDialogService/index.tsx +39 -0
- package/src/services/ActionDialogService/service.tsx +355 -0
- package/src/services/ActionDialogService/shared.ts +204 -0
- package/src/services/ActionDialogService/types.ts +197 -0
- package/src/services/CardToastService/README.md +128 -0
- package/src/services/CardToastService/index.tsx +1284 -0
- package/src/services/ImagePreviewService/README.md +67 -0
- package/src/services/ImagePreviewService/index.tsx +2148 -0
- package/src/services/LoadingService/README.md +128 -0
- package/src/services/LoadingService/index.tsx +1113 -0
- package/src/services/PermissionPurposeDialogService/README.md +80 -0
- package/src/services/PermissionPurposeDialogService/index.tsx +449 -0
- package/src/services/PickerService/README.md +154 -0
- package/src/services/PickerService/index.tsx +410 -0
- package/src/theme/ThemeProvider.tsx +40 -0
- package/src/theme/defaultTheme.ts +30 -0
- package/src/theme/mergeTheme.ts +16 -0
- package/src/theme/types.ts +36 -0
- package/src/theme/useTheme.ts +10 -0
- package/src/types/svg.d.ts +9 -0
- package/src/types/vant-area-data.d.ts +19 -0
- package/src/ui/Accordion/README.md +67 -0
- package/src/ui/Accordion/index.tsx +1221 -0
- package/src/ui/AddressCascader/README.md +144 -0
- package/src/ui/AddressCascader/index.tsx +1084 -0
- package/src/ui/BetweenTime/README.md +490 -0
- package/src/ui/BetweenTime/index.tsx +1001 -0
- package/src/ui/Button/README.md +186 -0
- package/src/ui/Button/index.tsx +1356 -0
- package/src/ui/Checkbox/README.md +211 -0
- package/src/ui/Checkbox/index.tsx +1231 -0
- package/src/ui/DatePicker/README.md +117 -0
- package/src/ui/DatePicker/index.tsx +295 -0
- package/src/ui/DatePicker/types.ts +115 -0
- package/src/ui/DatePicker/utils.ts +405 -0
- package/src/ui/LinkedScroll/README.md +55 -0
- package/src/ui/LinkedScroll/index.tsx +809 -0
- package/src/ui/LoadingSpinner/index.tsx +104 -0
- package/src/ui/Picker/README.md +190 -0
- package/src/ui/Picker/actionBar.tsx +70 -0
- package/src/ui/Picker/index.tsx +694 -0
- package/src/ui/Picker/types.ts +94 -0
- package/src/ui/Picker/utils.ts +239 -0
- package/src/ui/Radio/README.md +207 -0
- package/src/ui/Radio/index.tsx +1117 -0
- package/src/ui/Sheet/README.md +82 -0
- package/src/ui/Sheet/index.tsx +1163 -0
- package/src/ui/Sheet/nativeBottom.tsx +683 -0
- package/src/ui/Sheet/nativeBottom.web.tsx +40 -0
- package/src/ui/Sheet/slots.tsx +75 -0
- package/src/ui/Sheet/types.ts +195 -0
- package/src/ui/SliderCaptcha/README.md +61 -0
- package/src/ui/SliderCaptcha/index.tsx +816 -0
- package/src/ui/Switch/README.md +143 -0
- package/src/ui/Switch/index.tsx +1092 -0
- package/src/ui/Text/README.md +157 -0
- package/src/ui/Text/index.tsx +450 -0
- package/src/ui/TextInput/README.md +197 -0
- package/src/ui/TextInput/TextInputPrimitive.tsx +44 -0
- package/src/ui/TextInput/index.tsx +942 -0
- package/src/ui/WheelColumn/README.md +104 -0
- package/src/ui/WheelColumn/ZKitWheelPickerNativeComponent.tsx +68 -0
- package/src/ui/WheelColumn/constants.ts +1 -0
- package/src/ui/WheelColumn/index.tsx +826 -0
- package/zkit-ui.podspec +19 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type {
|
|
3
|
+
ActionDialogAction,
|
|
4
|
+
ActionDialogActionRole,
|
|
5
|
+
ActionDialogActionTone,
|
|
6
|
+
ActionDialogActionVariant,
|
|
7
|
+
ActionDialogColors,
|
|
8
|
+
ActionDialogDismissOptions,
|
|
9
|
+
ActionDialogFooterLayout,
|
|
10
|
+
ActionDialogKeyboardOptions,
|
|
11
|
+
ActionDialogLabels,
|
|
12
|
+
ActionDialogLayoutOptions,
|
|
13
|
+
ActionDialogOpenOptions,
|
|
14
|
+
ActionDialogResolvedAction,
|
|
15
|
+
ActionDialogResolvedFooterLayout,
|
|
16
|
+
ActionDialogResult,
|
|
17
|
+
ActionDialogSemanticActionOptions,
|
|
18
|
+
} from './types';
|
|
19
|
+
|
|
20
|
+
export const ACTION_DIALOG_DEFAULT_Z_INDEX = 4200;
|
|
21
|
+
|
|
22
|
+
export const ACTION_DIALOG_DEFAULT_LAYOUT: Required<ActionDialogLayoutOptions> = {
|
|
23
|
+
width: 320,
|
|
24
|
+
maxWidth: 380,
|
|
25
|
+
contentPadding: 20,
|
|
26
|
+
radius: 20,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const ACTION_DIALOG_DEFAULT_DISMISS: Required<ActionDialogDismissOptions> = {
|
|
30
|
+
overlayPress: false,
|
|
31
|
+
backPress: true,
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const ACTION_DIALOG_DEFAULT_KEYBOARD: Required<ActionDialogKeyboardOptions> = {
|
|
35
|
+
avoid: true,
|
|
36
|
+
dismissOnOverlayPress: true,
|
|
37
|
+
dismissOnClose: true,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const ACTION_DIALOG_DEFAULT_COLORS: Required<ActionDialogColors> = {
|
|
41
|
+
backdrop: 'rgba(17, 24, 39, 0.48)',
|
|
42
|
+
surface: '',
|
|
43
|
+
title: '',
|
|
44
|
+
message: '',
|
|
45
|
+
border: '',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const AUTO_ROW_MAX_ACTIONS = 3;
|
|
49
|
+
const AUTO_ROW_MAX_LABEL_WEIGHT = 8;
|
|
50
|
+
|
|
51
|
+
export function isFiniteNumber(value: unknown): value is number {
|
|
52
|
+
return typeof value === 'number' && Number.isFinite(value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function positiveNumber(value: number | undefined, fallback: number) {
|
|
56
|
+
return isFiniteNumber(value) && value > 0 ? value : fallback;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function resolveLayout(layout: ActionDialogLayoutOptions | undefined): Required<ActionDialogLayoutOptions> {
|
|
60
|
+
return {
|
|
61
|
+
width: positiveNumber(layout?.width, ACTION_DIALOG_DEFAULT_LAYOUT.width),
|
|
62
|
+
maxWidth: positiveNumber(layout?.maxWidth, ACTION_DIALOG_DEFAULT_LAYOUT.maxWidth),
|
|
63
|
+
contentPadding: positiveNumber(layout?.contentPadding, ACTION_DIALOG_DEFAULT_LAYOUT.contentPadding),
|
|
64
|
+
radius: positiveNumber(layout?.radius, ACTION_DIALOG_DEFAULT_LAYOUT.radius),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function resolveDismissOptions(
|
|
69
|
+
dismissible: boolean,
|
|
70
|
+
dismiss: ActionDialogDismissOptions | undefined
|
|
71
|
+
): Required<ActionDialogDismissOptions> {
|
|
72
|
+
return {
|
|
73
|
+
overlayPress: dismissible && (dismiss?.overlayPress ?? ACTION_DIALOG_DEFAULT_DISMISS.overlayPress),
|
|
74
|
+
backPress: dismissible && (dismiss?.backPress ?? ACTION_DIALOG_DEFAULT_DISMISS.backPress),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function resolveKeyboardOptions(
|
|
79
|
+
keyboard: ActionDialogKeyboardOptions | undefined
|
|
80
|
+
): Required<ActionDialogKeyboardOptions> {
|
|
81
|
+
return {
|
|
82
|
+
avoid: keyboard?.avoid ?? ACTION_DIALOG_DEFAULT_KEYBOARD.avoid,
|
|
83
|
+
dismissOnOverlayPress:
|
|
84
|
+
keyboard?.dismissOnOverlayPress ?? ACTION_DIALOG_DEFAULT_KEYBOARD.dismissOnOverlayPress,
|
|
85
|
+
dismissOnClose: keyboard?.dismissOnClose ?? ACTION_DIALOG_DEFAULT_KEYBOARD.dismissOnClose,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function resolveFooterLayout(
|
|
90
|
+
layout: ActionDialogFooterLayout | undefined,
|
|
91
|
+
actions: readonly Pick<ActionDialogResolvedAction, 'label'>[]
|
|
92
|
+
): ActionDialogResolvedFooterLayout {
|
|
93
|
+
if (layout === 'bar' || layout === 'row' || layout === 'stack') return layout;
|
|
94
|
+
if (actions.length <= 2) return 'row';
|
|
95
|
+
if (actions.length > AUTO_ROW_MAX_ACTIONS) return 'stack';
|
|
96
|
+
return actions.every((action) => {
|
|
97
|
+
const weight = getPrimitiveLabelWeight(action.label);
|
|
98
|
+
return weight != null && weight <= AUTO_ROW_MAX_LABEL_WEIGHT;
|
|
99
|
+
})
|
|
100
|
+
? 'row'
|
|
101
|
+
: 'stack';
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function defaultToneForRole(role: ActionDialogActionRole): ActionDialogActionTone {
|
|
105
|
+
if (role === 'confirm') return 'primary';
|
|
106
|
+
return 'neutral';
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getPrimitiveLabelWeight(label: React.ReactNode) {
|
|
110
|
+
const text = typeof label === 'string' || typeof label === 'number' ? String(label).trim() : '';
|
|
111
|
+
if (!text) return null;
|
|
112
|
+
|
|
113
|
+
return Array.from(text).reduce((total, char) => {
|
|
114
|
+
const code = char.codePointAt(0) ?? 0;
|
|
115
|
+
return total + (code > 0xff ? 2 : 1);
|
|
116
|
+
}, 0);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function defaultVariantForTone(tone: ActionDialogActionTone): ActionDialogActionVariant {
|
|
120
|
+
return tone === 'neutral' ? 'soft' : 'solid';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function fallbackLabel(role: ActionDialogActionRole, key: string, labels: ActionDialogLabels): React.ReactNode {
|
|
124
|
+
if (role === 'confirm') return labels.confirm;
|
|
125
|
+
if (role === 'cancel') return labels.cancel;
|
|
126
|
+
return key;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function resolveActions(
|
|
130
|
+
actions: readonly ActionDialogAction[] | undefined,
|
|
131
|
+
labels: ActionDialogLabels
|
|
132
|
+
): ActionDialogResolvedAction[] {
|
|
133
|
+
if (!actions?.length) return [];
|
|
134
|
+
|
|
135
|
+
return actions.map((action, index) => {
|
|
136
|
+
const role = action.role ?? 'neutral';
|
|
137
|
+
const key = action.key ?? `${role}-${index}`;
|
|
138
|
+
const tone = action.tone ?? defaultToneForRole(role);
|
|
139
|
+
const variant = action.variant ?? defaultVariantForTone(tone);
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
key,
|
|
143
|
+
role,
|
|
144
|
+
label: action.label ?? fallbackLabel(role, key, labels),
|
|
145
|
+
tone,
|
|
146
|
+
variant,
|
|
147
|
+
closeOnPress: action.closeOnPress ?? true,
|
|
148
|
+
disabled: Boolean(action.disabled),
|
|
149
|
+
loading: Boolean(action.loading),
|
|
150
|
+
accessibilityLabel: action.accessibilityLabel,
|
|
151
|
+
testID: action.testID,
|
|
152
|
+
onPress: action.onPress,
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function createActionResult(action: ActionDialogResolvedAction): ActionDialogResult {
|
|
158
|
+
return {
|
|
159
|
+
type: 'action',
|
|
160
|
+
action: {
|
|
161
|
+
key: action.key,
|
|
162
|
+
role: action.role,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export function mergeOpenOptions(
|
|
168
|
+
base: ActionDialogOpenOptions,
|
|
169
|
+
patch: Partial<ActionDialogOpenOptions>
|
|
170
|
+
): ActionDialogOpenOptions {
|
|
171
|
+
return {
|
|
172
|
+
...base,
|
|
173
|
+
...patch,
|
|
174
|
+
colors: { ...base.colors, ...patch.colors },
|
|
175
|
+
dismiss: { ...base.dismiss, ...patch.dismiss },
|
|
176
|
+
footer: { ...base.footer, ...patch.footer },
|
|
177
|
+
keyboard: { ...base.keyboard, ...patch.keyboard },
|
|
178
|
+
labels: { ...base.labels, ...patch.labels },
|
|
179
|
+
layer: { ...base.layer, ...patch.layer },
|
|
180
|
+
layout: { ...base.layout, ...patch.layout },
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export function createSemanticAction(
|
|
185
|
+
input: ActionDialogSemanticActionOptions | undefined,
|
|
186
|
+
fallbackLabel: React.ReactNode | undefined,
|
|
187
|
+
key: string,
|
|
188
|
+
role: ActionDialogActionRole,
|
|
189
|
+
tone: ActionDialogActionTone
|
|
190
|
+
): ActionDialogAction {
|
|
191
|
+
return {
|
|
192
|
+
key: input?.key ?? key,
|
|
193
|
+
role,
|
|
194
|
+
label: input?.label ?? fallbackLabel,
|
|
195
|
+
tone: input?.tone ?? tone,
|
|
196
|
+
variant: input?.variant,
|
|
197
|
+
closeOnPress: input?.closeOnPress ?? true,
|
|
198
|
+
disabled: input?.disabled,
|
|
199
|
+
loading: input?.loading,
|
|
200
|
+
accessibilityLabel: input?.accessibilityLabel,
|
|
201
|
+
testID: input?.testID,
|
|
202
|
+
onPress: input?.onPress,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type { ModalProps, StyleProp, ViewProps, ViewStyle } from 'react-native';
|
|
3
|
+
|
|
4
|
+
export type ActionDialogActionRole = 'confirm' | 'cancel' | 'neutral';
|
|
5
|
+
export type ActionDialogActionTone = 'primary' | 'neutral' | 'danger';
|
|
6
|
+
export type ActionDialogActionVariant = 'solid' | 'soft' | 'outline' | 'ghost';
|
|
7
|
+
export type ActionDialogFooterLayout = 'auto' | 'row' | 'stack' | 'bar';
|
|
8
|
+
export type ActionDialogResolvedFooterLayout = Exclude<ActionDialogFooterLayout, 'auto'>;
|
|
9
|
+
export type ActionDialogDismissReason = 'api' | 'back' | 'overlay' | 'replace' | 'unmount';
|
|
10
|
+
export type ActionDialogOpenChangeReason = 'action' | ActionDialogDismissReason;
|
|
11
|
+
export type ActionDialogCollisionStrategy = 'replace' | 'queue';
|
|
12
|
+
export type ActionDialogHostMode = 'modal' | 'inline';
|
|
13
|
+
export type ActionDialogMotion = 'none' | 'fade' | 'scale';
|
|
14
|
+
|
|
15
|
+
export type ActionDialogActionResult = {
|
|
16
|
+
type: 'action';
|
|
17
|
+
action: {
|
|
18
|
+
key: string;
|
|
19
|
+
role: ActionDialogActionRole;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type ActionDialogDismissResult = {
|
|
24
|
+
type: 'dismiss';
|
|
25
|
+
reason: ActionDialogDismissReason;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type ActionDialogResult = ActionDialogActionResult | ActionDialogDismissResult;
|
|
29
|
+
|
|
30
|
+
export type ActionDialogActionContext = {
|
|
31
|
+
action: ActionDialogResolvedAction;
|
|
32
|
+
close: () => void;
|
|
33
|
+
dismiss: (reason?: Extract<ActionDialogDismissReason, 'api'>) => void;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type ActionDialogActionPressResult = void | false;
|
|
37
|
+
|
|
38
|
+
export type ActionDialogAction = {
|
|
39
|
+
key?: string;
|
|
40
|
+
role?: ActionDialogActionRole;
|
|
41
|
+
label?: React.ReactNode;
|
|
42
|
+
tone?: ActionDialogActionTone;
|
|
43
|
+
variant?: ActionDialogActionVariant;
|
|
44
|
+
closeOnPress?: boolean;
|
|
45
|
+
disabled?: boolean;
|
|
46
|
+
loading?: boolean;
|
|
47
|
+
accessibilityLabel?: string;
|
|
48
|
+
testID?: ViewProps['testID'];
|
|
49
|
+
onPress?: (context: ActionDialogActionContext) => ActionDialogActionPressResult;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export type ActionDialogResolvedAction = Required<
|
|
53
|
+
Pick<ActionDialogAction, 'closeOnPress' | 'disabled' | 'key' | 'loading' | 'role' | 'tone' | 'variant'>
|
|
54
|
+
> &
|
|
55
|
+
Pick<ActionDialogAction, 'accessibilityLabel' | 'label' | 'onPress' | 'testID'>;
|
|
56
|
+
|
|
57
|
+
export type ActionDialogFooterRenderContext = {
|
|
58
|
+
actions: ActionDialogResolvedAction[];
|
|
59
|
+
layout: ActionDialogResolvedFooterLayout;
|
|
60
|
+
close: () => void;
|
|
61
|
+
pressAction: (key: string) => void;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export type ActionDialogFooterOptions = {
|
|
65
|
+
layout?: ActionDialogFooterLayout;
|
|
66
|
+
render?: (context: ActionDialogFooterRenderContext) => React.ReactNode;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export type ActionDialogDismissOptions = {
|
|
70
|
+
overlayPress?: boolean;
|
|
71
|
+
backPress?: boolean;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export type ActionDialogKeyboardOptions = {
|
|
75
|
+
avoid?: boolean;
|
|
76
|
+
dismissOnOverlayPress?: boolean;
|
|
77
|
+
dismissOnClose?: boolean;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export type ActionDialogLayoutOptions = {
|
|
81
|
+
width?: number;
|
|
82
|
+
maxWidth?: number;
|
|
83
|
+
contentPadding?: number;
|
|
84
|
+
radius?: number;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export type ActionDialogLayerOptions = {
|
|
88
|
+
zIndex?: number;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export type ActionDialogColors = {
|
|
92
|
+
backdrop?: string;
|
|
93
|
+
surface?: string;
|
|
94
|
+
title?: string;
|
|
95
|
+
message?: string;
|
|
96
|
+
border?: string;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type ActionDialogLabels = {
|
|
100
|
+
confirm: string;
|
|
101
|
+
cancel: string;
|
|
102
|
+
close: string;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export type ActionDialogOpenChangeMeta = {
|
|
106
|
+
reason: ActionDialogOpenChangeReason;
|
|
107
|
+
result?: ActionDialogResult;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type ActionDialogRef = {
|
|
111
|
+
close: (reason?: Extract<ActionDialogDismissReason, 'api'>) => void;
|
|
112
|
+
pressAction: (key: string) => void;
|
|
113
|
+
getOpen: () => boolean;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export type ActionDialogProps = {
|
|
117
|
+
open?: boolean;
|
|
118
|
+
defaultOpen?: boolean;
|
|
119
|
+
onOpenChange?: (open: boolean, meta: ActionDialogOpenChangeMeta) => void;
|
|
120
|
+
onClose?: (result: ActionDialogResult) => void;
|
|
121
|
+
onDismissComplete?: () => void;
|
|
122
|
+
onActionError?: (error: unknown, action: ActionDialogResolvedAction) => void;
|
|
123
|
+
|
|
124
|
+
title?: React.ReactNode;
|
|
125
|
+
message?: React.ReactNode;
|
|
126
|
+
children?: React.ReactNode;
|
|
127
|
+
actions?: readonly ActionDialogAction[];
|
|
128
|
+
footer?: ActionDialogFooterOptions;
|
|
129
|
+
|
|
130
|
+
disabled?: boolean;
|
|
131
|
+
dismissible?: boolean;
|
|
132
|
+
dismiss?: ActionDialogDismissOptions;
|
|
133
|
+
hostMode?: ActionDialogHostMode;
|
|
134
|
+
keyboard?: ActionDialogKeyboardOptions;
|
|
135
|
+
layout?: ActionDialogLayoutOptions;
|
|
136
|
+
layer?: ActionDialogLayerOptions;
|
|
137
|
+
colors?: Partial<ActionDialogColors>;
|
|
138
|
+
labels?: Partial<ActionDialogLabels>;
|
|
139
|
+
motion?: ActionDialogMotion;
|
|
140
|
+
modalProps?: Omit<
|
|
141
|
+
ModalProps,
|
|
142
|
+
'children' | 'onRequestClose' | 'presentationStyle' | 'statusBarTranslucent' | 'transparent' | 'visible'
|
|
143
|
+
>;
|
|
144
|
+
|
|
145
|
+
style?: StyleProp<ViewStyle>;
|
|
146
|
+
testID?: ViewProps['testID'];
|
|
147
|
+
accessibilityLabel?: ViewProps['accessibilityLabel'];
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export type ActionDialogSemanticActionOptions = Omit<Partial<ActionDialogAction>, 'role'>;
|
|
151
|
+
|
|
152
|
+
export type ActionDialogOpenOptions = Omit<
|
|
153
|
+
ActionDialogProps,
|
|
154
|
+
'defaultOpen' | 'modalProps' | 'onDismissComplete' | 'onOpenChange' | 'open'
|
|
155
|
+
> & {
|
|
156
|
+
scopeKey?: string;
|
|
157
|
+
collisionStrategy?: ActionDialogCollisionStrategy;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export type ActionDialogConfirmOptions = Omit<ActionDialogOpenOptions, 'actions' | 'footer'> & {
|
|
161
|
+
confirmLabel?: React.ReactNode;
|
|
162
|
+
cancelLabel?: React.ReactNode;
|
|
163
|
+
confirmAction?: ActionDialogSemanticActionOptions;
|
|
164
|
+
cancelAction?: ActionDialogSemanticActionOptions;
|
|
165
|
+
tone?: 'default' | 'danger';
|
|
166
|
+
footer?: Pick<ActionDialogFooterOptions, 'layout'>;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
export type ActionDialogAlertOptions = Omit<ActionDialogOpenOptions, 'actions' | 'footer'> & {
|
|
170
|
+
confirmLabel?: React.ReactNode;
|
|
171
|
+
confirmAction?: ActionDialogSemanticActionOptions;
|
|
172
|
+
tone?: 'default' | 'danger';
|
|
173
|
+
footer?: Pick<ActionDialogFooterOptions, 'layout'>;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export type ActionDialogHandle = {
|
|
177
|
+
id: string;
|
|
178
|
+
result: Promise<ActionDialogResult>;
|
|
179
|
+
close: (reason?: Extract<ActionDialogDismissReason, 'api'>) => void;
|
|
180
|
+
update: (patch: Partial<ActionDialogOpenOptions>) => void;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export type ActionDialogSnapshot = {
|
|
184
|
+
open: boolean;
|
|
185
|
+
activeId: string | null;
|
|
186
|
+
queuedCount: number;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export type ActionDialogService = {
|
|
190
|
+
open: (options?: ActionDialogOpenOptions) => ActionDialogHandle;
|
|
191
|
+
confirm: (options?: ActionDialogConfirmOptions) => Promise<boolean>;
|
|
192
|
+
alert: (options?: ActionDialogAlertOptions) => Promise<void>;
|
|
193
|
+
close: (reason?: Extract<ActionDialogDismissReason, 'api'>) => void;
|
|
194
|
+
closeByScope: (scopeKey: string) => void;
|
|
195
|
+
closeAll: (reason?: Extract<ActionDialogDismissReason, 'api'>) => void;
|
|
196
|
+
getSnapshot: () => ActionDialogSnapshot;
|
|
197
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# CardToastService
|
|
2
|
+
|
|
3
|
+
全局卡片 Toast 服务,适合保存成功、网络失败、轻量操作反馈这类不应打断用户流程的提示。
|
|
4
|
+
|
|
5
|
+
`ComponentLibProvider` 已内置 `ToastProvider`。如果单独接入,需要把 `ToastProvider` 放在应用根部。
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { ToastProvider } from 'zkit-ui';
|
|
9
|
+
|
|
10
|
+
export function App() {
|
|
11
|
+
return <ToastProvider>{/* app */}</ToastProvider>;
|
|
12
|
+
}
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 默认行为
|
|
16
|
+
|
|
17
|
+
- 默认视觉保持原卡片 Toast:语义 webp 图标、淡色背景、细边框、`wp(320)` 宽度、`wp(10)` 圆角和 iOS sheen 动效不变。
|
|
18
|
+
- 默认 `placement: 'top'`,位置会叠加 safe area,额外偏移保持原来的 `35` 设计像素。
|
|
19
|
+
- 默认 `strategy: 'replace'`,新提示替换当前提示,避免连续操作时堆积。
|
|
20
|
+
- 默认 `duration: 2400`,传 `duration: 0` 时不会自动关闭,并会自动显示关闭按钮。
|
|
21
|
+
- 动画只使用 opacity / transform,避免布局动画和 JS 高频驱动。
|
|
22
|
+
- Toast 是全局轻反馈层,默认显示在 Dialog、Picker 等交互遮罩之上;阻塞式 Loading、图片预览等最高优先级浮层仍应高于 Toast。
|
|
23
|
+
|
|
24
|
+
## 使用方式
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { toast } from 'zkit-ui';
|
|
28
|
+
|
|
29
|
+
toast.success('保存成功');
|
|
30
|
+
toast.error('网络错误', {
|
|
31
|
+
description: '请检查网络后重试',
|
|
32
|
+
duration: 3200,
|
|
33
|
+
});
|
|
34
|
+
toast.info('已刷新', { placement: 'bottom' });
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
完整配置入口:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
const handle = toast.show({
|
|
41
|
+
tone: 'warning',
|
|
42
|
+
title: '资料未完整',
|
|
43
|
+
description: '请补充手机号后继续',
|
|
44
|
+
action: {
|
|
45
|
+
label: '去补充',
|
|
46
|
+
onPress: () => {
|
|
47
|
+
// navigate(...)
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
handle.update({ tone: 'success', title: '已补充', description: undefined });
|
|
53
|
+
handle.dismiss();
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 队列策略
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
toast.info('按顺序展示', { strategy: 'queue' });
|
|
60
|
+
toast.success('可堆叠提示', { strategy: 'stack', maxVisible: 3 });
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| strategy | 行为 |
|
|
64
|
+
| --- | --- |
|
|
65
|
+
| `replace` | 关闭当前可见 Toast,展示最新一条。默认值 |
|
|
66
|
+
| `queue` | 当前 Toast 完整退出后,再展示下一条 |
|
|
67
|
+
| `stack` | 同位置最多展示 `maxVisible` 条,超出时关闭最旧一条 |
|
|
68
|
+
|
|
69
|
+
## 全局默认值
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
toast.configure({
|
|
73
|
+
placement: 'top',
|
|
74
|
+
offset: 35,
|
|
75
|
+
duration: 2400,
|
|
76
|
+
strategy: 'replace',
|
|
77
|
+
maxVisible: 3,
|
|
78
|
+
closeButton: false,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
单条 Toast 的 options 优先级高于 `configure`。
|
|
83
|
+
|
|
84
|
+
## 自定义渲染
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
toast.custom(
|
|
88
|
+
({ dismiss }) => (
|
|
89
|
+
<Pressable onPress={() => dismiss()}>
|
|
90
|
+
<Text>自定义 Toast</Text>
|
|
91
|
+
</Pressable>
|
|
92
|
+
),
|
|
93
|
+
{
|
|
94
|
+
accessibilityLabel: '自定义 Toast',
|
|
95
|
+
duration: 0,
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
自定义渲染仍由 `ToastProvider` 管理生命周期、队列、safe area 和退出清理。自定义内容里的像素尺寸仍应使用 `wp(...)`。
|
|
101
|
+
|
|
102
|
+
## API 摘要
|
|
103
|
+
|
|
104
|
+
| API | 说明 |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `toast.show(options)` | 展示完整配置的 Toast,返回 `ToastHandle` |
|
|
107
|
+
| `toast.success/error/warning/info/neutral(title, options?)` | 语义快捷入口 |
|
|
108
|
+
| `toast.custom(render, options?)` | 自定义内容入口 |
|
|
109
|
+
| `toast.update(idOrHandle, patch)` | 更新可见或排队中的 Toast |
|
|
110
|
+
| `toast.dismiss(idOrHandle?)` | 关闭指定 Toast;不传时关闭最新可见 Toast |
|
|
111
|
+
| `toast.dismissAll()` | 关闭所有可见和排队 Toast |
|
|
112
|
+
| `toast.configure(defaults)` | 设置全局默认值 |
|
|
113
|
+
|
|
114
|
+
常用 options:
|
|
115
|
+
|
|
116
|
+
| 字段 | 类型 | 说明 |
|
|
117
|
+
| --- | --- | --- |
|
|
118
|
+
| `tone` | `'success' \| 'error' \| 'warning' \| 'info' \| 'neutral'` | 语义色 |
|
|
119
|
+
| `title` | `ReactNode` | 主文案 |
|
|
120
|
+
| `description` | `ReactNode` | 辅助文案 |
|
|
121
|
+
| `duration` | `number` | 自动关闭时长,`0` 表示常驻 |
|
|
122
|
+
| `placement` | `'top' \| 'bottom'` | 出现位置 |
|
|
123
|
+
| `offset` | `number` | 相对 safe area 的设计像素偏移 |
|
|
124
|
+
| `strategy` | `'replace' \| 'queue' \| 'stack'` | 连续触发策略 |
|
|
125
|
+
| `action` | `ToastAction` | 可点击动作 |
|
|
126
|
+
| `closeButton` | `boolean` | 是否展示关闭按钮 |
|
|
127
|
+
| `icon` | `ReactNode \| false \| render` | 自定义图标或隐藏图标 |
|
|
128
|
+
| `render` | `(context) => ReactNode` | 完全自定义内容 |
|