react-native-unified-action-sheet 0.1.1 → 0.3.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/CHANGELOG.md +66 -1
- package/README.md +38 -105
- package/android/build.gradle +28 -1
- package/android/src/main/java/com/unifiedactionsheet/ActionSheetOptions.kt +6 -2
- package/android/src/main/java/com/unifiedactionsheet/PromptOptions.kt +132 -0
- package/android/src/main/java/com/unifiedactionsheet/SheetContentBuilder.kt +31 -0
- package/android/src/main/java/com/unifiedactionsheet/SheetPresenters.kt +54 -0
- package/android/src/main/java/com/unifiedactionsheet/UnifiedActionSheetModule.kt +61 -0
- package/android/src/material/java/com/unifiedactionsheet/BottomSheetPresenterFactory.kt +10 -0
- package/android/src/material/java/com/unifiedactionsheet/MaterialBottomSheetPresenter.kt +90 -0
- package/android/src/material/res/values/unified_action_sheet_bottom_sheet.xml +22 -0
- package/android/src/noMaterial/java/com/unifiedactionsheet/BottomSheetPresenterFactory.kt +10 -0
- package/app.plugin.js +1 -0
- package/ios/BottomSheetViewController.swift +208 -0
- package/ios/UnifiedActionSheet.mm +73 -1
- package/ios/UnifiedActionSheetImpl.swift +248 -11
- package/jest/index.d.ts +15 -1
- package/jest/index.js +28 -0
- package/lib/commonjs/NativeUnifiedActionSheet.js.map +1 -1
- package/lib/commonjs/action-sheet-options.interface.js +4 -0
- package/lib/commonjs/common-options.interface.js +2 -0
- package/lib/commonjs/common-options.interface.js.map +1 -0
- package/lib/commonjs/index.js +57 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/prompt-options.interface.js +6 -0
- package/lib/commonjs/prompt-options.interface.js.map +1 -0
- package/lib/module/NativeUnifiedActionSheet.js.map +1 -1
- package/lib/module/action-sheet-options.interface.js +2 -0
- package/lib/module/common-options.interface.js +2 -0
- package/lib/module/common-options.interface.js.map +1 -0
- package/lib/module/index.js +55 -4
- package/lib/module/index.js.map +1 -1
- package/lib/module/prompt-options.interface.js +4 -0
- package/lib/module/prompt-options.interface.js.map +1 -0
- package/lib/typescript/commonjs/src/NativeUnifiedActionSheet.d.ts +23 -0
- package/lib/typescript/commonjs/src/NativeUnifiedActionSheet.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/action-sheet-options.interface.d.ts +5 -14
- package/lib/typescript/commonjs/src/action-sheet-options.interface.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/common-options.interface.d.ts +17 -0
- package/lib/typescript/commonjs/src/common-options.interface.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +4 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/prompt-options.interface.d.ts +19 -0
- package/lib/typescript/commonjs/src/prompt-options.interface.d.ts.map +1 -0
- package/lib/typescript/module/src/NativeUnifiedActionSheet.d.ts +23 -0
- package/lib/typescript/module/src/NativeUnifiedActionSheet.d.ts.map +1 -1
- package/lib/typescript/module/src/action-sheet-options.interface.d.ts +5 -14
- package/lib/typescript/module/src/action-sheet-options.interface.d.ts.map +1 -1
- package/lib/typescript/module/src/common-options.interface.d.ts +17 -0
- package/lib/typescript/module/src/common-options.interface.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +4 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/prompt-options.interface.d.ts +19 -0
- package/lib/typescript/module/src/prompt-options.interface.d.ts.map +1 -0
- package/package.json +12 -2
- package/plugin/withUnifiedActionSheet.js +58 -0
- package/src/NativeUnifiedActionSheet.ts +22 -0
- package/src/action-sheet-options.interface.ts +10 -20
- package/src/common-options.interface.ts +18 -0
- package/src/index.tsx +100 -6
- package/src/prompt-options.interface.ts +27 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface BaseButtonInterface {
|
|
2
|
+
label: string;
|
|
3
|
+
style?: 'cancel' | 'destructive';
|
|
4
|
+
disabled?: boolean;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface BaseOptionsInterface {
|
|
8
|
+
title?: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
tintColor?: string;
|
|
11
|
+
cancelButtonTintColor?: string;
|
|
12
|
+
destructiveColor?: string;
|
|
13
|
+
userInterfaceStyle?: 'light' | 'dark';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface BaseAndroidOptionsInterface {
|
|
17
|
+
buttonTextAlignment?: 'start' | 'center';
|
|
18
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -3,6 +3,25 @@ import { Platform } from 'react-native';
|
|
|
3
3
|
import type { Spec } from './NativeUnifiedActionSheet';
|
|
4
4
|
import type { ActionSheetOptionsInterface } from './action-sheet-options.interface';
|
|
5
5
|
|
|
6
|
+
export type {
|
|
7
|
+
BaseButtonInterface,
|
|
8
|
+
BaseOptionsInterface,
|
|
9
|
+
BaseAndroidOptionsInterface,
|
|
10
|
+
} from './common-options.interface';
|
|
11
|
+
|
|
12
|
+
export type {
|
|
13
|
+
PromptButtonInterface,
|
|
14
|
+
PromptCommonOptionsInterface,
|
|
15
|
+
PromptAndroidOptionsInterface,
|
|
16
|
+
PromptOptionsInterface,
|
|
17
|
+
PromptResultInterface,
|
|
18
|
+
} from './prompt-options.interface';
|
|
19
|
+
import type { BaseButtonInterface } from './common-options.interface';
|
|
20
|
+
import type {
|
|
21
|
+
PromptOptionsInterface,
|
|
22
|
+
PromptResultInterface,
|
|
23
|
+
} from './prompt-options.interface';
|
|
24
|
+
|
|
6
25
|
export type {
|
|
7
26
|
ActionSheetAnchorInterface,
|
|
8
27
|
ActionSheetButtonInterface,
|
|
@@ -34,13 +53,27 @@ const toWireOptions = ({
|
|
|
34
53
|
// crosses the bridge. Omit<> would not strip it at runtime.
|
|
35
54
|
anchor: _anchor,
|
|
36
55
|
...rest
|
|
37
|
-
}: ActionSheetOptionsInterface): WireOptions => {
|
|
56
|
+
}: ActionSheetOptionsInterface): WireOptions => ({
|
|
57
|
+
...rest,
|
|
58
|
+
...toWireButtons(options),
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
type WirePromptOptions = Omit<PromptOptionsInterface, 'options'> & {
|
|
62
|
+
options: string[];
|
|
63
|
+
cancelButtonIndex?: number;
|
|
64
|
+
destructiveButtonIndices?: number[];
|
|
65
|
+
disabledButtonIndices?: number[];
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/// Same flattening as the sheet: labels plus index sets. Kept generic over the
|
|
69
|
+
/// button shape so the two APIs cannot disagree about what 'cancel' means.
|
|
70
|
+
const toWireButtons = (buttons: ReadonlyArray<BaseButtonInterface>) => {
|
|
38
71
|
const labels: string[] = [];
|
|
39
72
|
const destructive: number[] = [];
|
|
40
73
|
const disabled: number[] = [];
|
|
41
74
|
let cancelButtonIndex: number | undefined;
|
|
42
75
|
|
|
43
|
-
|
|
76
|
+
buttons.forEach((button, index) => {
|
|
44
77
|
labels.push(button.label);
|
|
45
78
|
|
|
46
79
|
if (button.style === 'destructive') destructive.push(index);
|
|
@@ -51,7 +84,6 @@ const toWireOptions = ({
|
|
|
51
84
|
});
|
|
52
85
|
|
|
53
86
|
return {
|
|
54
|
-
...rest,
|
|
55
87
|
options: labels,
|
|
56
88
|
...(cancelButtonIndex == null ? {} : { cancelButtonIndex }),
|
|
57
89
|
...(destructive.length === 0
|
|
@@ -72,6 +104,33 @@ const showWithNativeModule = (
|
|
|
72
104
|
)
|
|
73
105
|
.catch(() => options.cancelButtonIndex ?? -1);
|
|
74
106
|
|
|
107
|
+
let warnedMaterialDisabled = false;
|
|
108
|
+
|
|
109
|
+
/// 'bottom' needs Material on Android, which the app opts into at build time.
|
|
110
|
+
/// Without it the sheet falls back to a centered dialog; say so once, in
|
|
111
|
+
/// development, since the fallback alone looks like the option was ignored.
|
|
112
|
+
const warnIfBottomUnavailable = (
|
|
113
|
+
presentationStyle: ActionSheetOptionsInterface['presentationStyle']
|
|
114
|
+
) => {
|
|
115
|
+
if (
|
|
116
|
+
!__DEV__ ||
|
|
117
|
+
warnedMaterialDisabled ||
|
|
118
|
+
Platform.OS !== 'android' ||
|
|
119
|
+
presentationStyle !== 'bottom' ||
|
|
120
|
+
nativeModule().getConstants().isMaterialEnabled
|
|
121
|
+
) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
warnedMaterialDisabled = true;
|
|
126
|
+
console.warn(
|
|
127
|
+
"react-native-unified-action-sheet: presentationStyle 'bottom' needs Material on Android, " +
|
|
128
|
+
'so this sheet falls back to a centered dialog. Set unifiedActionSheet.material=true in ' +
|
|
129
|
+
"android/gradle.properties, or add ['react-native-unified-action-sheet', { material: true }] " +
|
|
130
|
+
'to your Expo plugins, then rebuild the app.'
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
75
134
|
/// The anchor is measured in JS and sent across as a rect, so neither native
|
|
76
135
|
/// module has to resolve a view: a ref's own measureInWindow is the supported
|
|
77
136
|
/// way to do this on both architectures, unlike a react tag.
|
|
@@ -111,9 +170,14 @@ export const showActionSheetWithOptions = (
|
|
|
111
170
|
return Promise.resolve(undefined);
|
|
112
171
|
}
|
|
113
172
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
173
|
+
warnIfBottomUnavailable(options.presentationStyle);
|
|
174
|
+
|
|
175
|
+
// A bottom sheet has no anchor, so don't measure one: on iPad a rect would
|
|
176
|
+
// turn the sheet into an arrowed popover pointing at it.
|
|
177
|
+
const anchor =
|
|
178
|
+
options.presentationStyle === 'bottom' ? undefined : options.anchor;
|
|
179
|
+
|
|
180
|
+
return withAnchorRect(wire, anchor).then(showWithNativeModule).then(press);
|
|
117
181
|
};
|
|
118
182
|
|
|
119
183
|
export const dismissActionSheet = (): void => {
|
|
@@ -129,3 +193,33 @@ export const dismissAllActionSheets = (): void => {
|
|
|
129
193
|
nativeModule().dismissAllActionSheets();
|
|
130
194
|
}
|
|
131
195
|
};
|
|
196
|
+
|
|
197
|
+
/// A prompt is the sheet's centered dialog with a text field: iOS presents a
|
|
198
|
+
/// UIAlertController alert with addTextField, Android the same AppCompatDialog
|
|
199
|
+
/// the centered style uses. React Native's own Alert.prompt is iOS-only and a
|
|
200
|
+
/// silent no-op on Android, which is the gap this fills.
|
|
201
|
+
export const showPromptWithOptions = (
|
|
202
|
+
options: PromptOptionsInterface
|
|
203
|
+
): Promise<PromptResultInterface | undefined> => {
|
|
204
|
+
const { options: buttons, ...rest } = options;
|
|
205
|
+
const wire: WirePromptOptions = { ...rest, ...toWireButtons(buttons) };
|
|
206
|
+
|
|
207
|
+
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
|
|
208
|
+
return Promise.resolve(undefined);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return nativeModule()
|
|
212
|
+
.showPromptWithOptions(wire)
|
|
213
|
+
.then((result) =>
|
|
214
|
+
// A programmatic dismiss resolves with no selection, matching the sheet.
|
|
215
|
+
result.buttonIndex === DISMISSED_BY_API ? undefined : result
|
|
216
|
+
)
|
|
217
|
+
.catch(() => ({ buttonIndex: wire.cancelButtonIndex ?? -1, text: '' }))
|
|
218
|
+
.then((result) => {
|
|
219
|
+
// The text goes to the handler, so a caller using onPress alone never
|
|
220
|
+
// has to read the resolved value.
|
|
221
|
+
if (result) buttons[result.buttonIndex]?.onPress?.(result.text);
|
|
222
|
+
|
|
223
|
+
return result;
|
|
224
|
+
});
|
|
225
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
BaseAndroidOptionsInterface,
|
|
3
|
+
BaseButtonInterface,
|
|
4
|
+
BaseOptionsInterface,
|
|
5
|
+
} from './common-options.interface';
|
|
6
|
+
|
|
7
|
+
export interface PromptButtonInterface extends BaseButtonInterface {
|
|
8
|
+
onPress?: (text: string) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PromptCommonOptionsInterface extends BaseOptionsInterface {
|
|
12
|
+
options: PromptButtonInterface[];
|
|
13
|
+
placeholder?: string;
|
|
14
|
+
defaultValue?: string;
|
|
15
|
+
keyboardType?: 'default' | 'email-address' | 'numeric' | 'phone-pad' | 'url';
|
|
16
|
+
secureTextEntry?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type PromptAndroidOptionsInterface = BaseAndroidOptionsInterface;
|
|
20
|
+
|
|
21
|
+
export interface PromptOptionsInterface
|
|
22
|
+
extends PromptCommonOptionsInterface, PromptAndroidOptionsInterface {}
|
|
23
|
+
|
|
24
|
+
export interface PromptResultInterface {
|
|
25
|
+
buttonIndex: number;
|
|
26
|
+
text: string;
|
|
27
|
+
}
|