react-native-unified-action-sheet 0.1.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 (49) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/LICENSE +20 -0
  3. package/README.md +167 -0
  4. package/android/build.gradle +51 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/unifiedactionsheet/ActionSheetOptions.kt +134 -0
  7. package/android/src/main/java/com/unifiedactionsheet/SheetContentBuilder.kt +159 -0
  8. package/android/src/main/java/com/unifiedactionsheet/SheetPresenters.kt +214 -0
  9. package/android/src/main/java/com/unifiedactionsheet/SheetTheming.kt +56 -0
  10. package/android/src/main/java/com/unifiedactionsheet/UnifiedActionSheetModule.kt +126 -0
  11. package/android/src/main/java/com/unifiedactionsheet/UnifiedActionSheetPackage.kt +30 -0
  12. package/ios/UnifiedActionSheet.h +5 -0
  13. package/ios/UnifiedActionSheet.mm +96 -0
  14. package/ios/UnifiedActionSheetImpl.swift +240 -0
  15. package/jest/index.d.ts +12 -0
  16. package/jest/index.js +46 -0
  17. package/lib/commonjs/NativeUnifiedActionSheet.js +9 -0
  18. package/lib/commonjs/NativeUnifiedActionSheet.js.map +1 -0
  19. package/lib/commonjs/action-sheet-options.interface.js +2 -0
  20. package/lib/commonjs/action-sheet-options.interface.js.map +1 -0
  21. package/lib/commonjs/index.js +104 -0
  22. package/lib/commonjs/index.js.map +1 -0
  23. package/lib/commonjs/package.json +1 -0
  24. package/lib/module/NativeUnifiedActionSheet.js +5 -0
  25. package/lib/module/NativeUnifiedActionSheet.js.map +1 -0
  26. package/lib/module/action-sheet-options.interface.js +2 -0
  27. package/lib/module/action-sheet-options.interface.js.map +1 -0
  28. package/lib/module/index.js +97 -0
  29. package/lib/module/index.js.map +1 -0
  30. package/lib/module/package.json +1 -0
  31. package/lib/typescript/commonjs/package.json +1 -0
  32. package/lib/typescript/commonjs/src/NativeUnifiedActionSheet.d.ts +29 -0
  33. package/lib/typescript/commonjs/src/NativeUnifiedActionSheet.d.ts.map +1 -0
  34. package/lib/typescript/commonjs/src/action-sheet-options.interface.d.ts +29 -0
  35. package/lib/typescript/commonjs/src/action-sheet-options.interface.d.ts.map +1 -0
  36. package/lib/typescript/commonjs/src/index.d.ts +6 -0
  37. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  38. package/lib/typescript/module/package.json +1 -0
  39. package/lib/typescript/module/src/NativeUnifiedActionSheet.d.ts +29 -0
  40. package/lib/typescript/module/src/NativeUnifiedActionSheet.d.ts.map +1 -0
  41. package/lib/typescript/module/src/action-sheet-options.interface.d.ts +29 -0
  42. package/lib/typescript/module/src/action-sheet-options.interface.d.ts.map +1 -0
  43. package/lib/typescript/module/src/index.d.ts +6 -0
  44. package/lib/typescript/module/src/index.d.ts.map +1 -0
  45. package/package.json +155 -0
  46. package/react-native-unified-action-sheet.podspec +23 -0
  47. package/src/NativeUnifiedActionSheet.ts +29 -0
  48. package/src/action-sheet-options.interface.ts +43 -0
  49. package/src/index.tsx +131 -0
@@ -0,0 +1,29 @@
1
+ import { type TurboModule } from 'react-native';
2
+ export interface Spec extends TurboModule {
3
+ showActionSheetWithOptions(options: {
4
+ options: string[];
5
+ cancelButtonIndex?: number;
6
+ destructiveButtonIndices?: number[];
7
+ title?: string;
8
+ message?: string;
9
+ tintColor?: string;
10
+ cancelButtonTintColor?: string;
11
+ destructiveColor?: string;
12
+ buttonTextAlignment?: string;
13
+ disabledButtonIndices?: number[];
14
+ userInterfaceStyle?: string;
15
+ presentationStyle?: string;
16
+ anchorAlignment?: string;
17
+ anchorRect?: {
18
+ x: number;
19
+ y: number;
20
+ width: number;
21
+ height: number;
22
+ };
23
+ }): Promise<number>;
24
+ dismissActionSheet(): void;
25
+ dismissAllActionSheets(): void;
26
+ }
27
+ declare const _default: Spec;
28
+ export default _default;
29
+ //# sourceMappingURL=NativeUnifiedActionSheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NativeUnifiedActionSheet.d.ts","sourceRoot":"","sources":["../../../../src/NativeUnifiedActionSheet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,0BAA0B,CAAC,OAAO,EAAE;QAClC,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;QACpC,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;QACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,UAAU,CAAC,EAAE;YACX,CAAC,EAAE,MAAM,CAAC;YACV,CAAC,EAAE,MAAM,CAAC;YACV,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpB,kBAAkB,IAAI,IAAI,CAAC;IAC3B,sBAAsB,IAAI,IAAI,CAAC;CAChC;;AAED,wBAA4E"}
@@ -0,0 +1,29 @@
1
+ export interface ActionSheetButtonInterface {
2
+ label: string;
3
+ style?: 'cancel' | 'destructive';
4
+ disabled?: boolean;
5
+ onPress?: () => void;
6
+ }
7
+ export interface ActionSheetAnchorInterface {
8
+ measureInWindow: (callback: (x: number, y: number, width: number, height: number) => void) => void;
9
+ }
10
+ export interface ActionSheetCommonOptionsInterface {
11
+ options: ActionSheetButtonInterface[];
12
+ title?: string;
13
+ message?: string;
14
+ tintColor?: string;
15
+ cancelButtonTintColor?: string;
16
+ userInterfaceStyle?: 'light' | 'dark';
17
+ anchor?: ActionSheetAnchorInterface | {
18
+ current: ActionSheetAnchorInterface | null;
19
+ } | null;
20
+ destructiveColor?: string;
21
+ presentationStyle?: 'centered' | 'anchored';
22
+ }
23
+ export interface ActionSheetAndroidOptionsInterface {
24
+ buttonTextAlignment?: 'start' | 'center';
25
+ anchorAlignment?: 'start' | 'center';
26
+ }
27
+ export interface ActionSheetOptionsInterface extends ActionSheetCommonOptionsInterface, ActionSheetAndroidOptionsInterface {
28
+ }
29
+ //# sourceMappingURL=action-sheet-options.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-sheet-options.interface.d.ts","sourceRoot":"","sources":["../../../../src/action-sheet-options.interface.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAGnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAID,MAAM,WAAW,0BAA0B;IACzC,eAAe,EAAE,CACf,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,KACpE,IAAI,CAAC;CACX;AAED,MAAM,WAAW,iCAAiC;IAChD,OAAO,EAAE,0BAA0B,EAAE,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACtC,MAAM,CAAC,EACH,0BAA0B,GAC1B;QAAE,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAAA;KAAE,GAC9C,IAAI,CAAC;IACT,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CAC7C;AAED,MAAM,WAAW,kCAAkC;IACjD,mBAAmB,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzC,eAAe,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CACtC;AAED,MAAM,WAAW,2BACf,SACE,iCAAiC,EACjC,kCAAkC;CAAG"}
@@ -0,0 +1,6 @@
1
+ import type { ActionSheetOptionsInterface } from './action-sheet-options.interface.js';
2
+ export type { ActionSheetAnchorInterface, ActionSheetButtonInterface, ActionSheetCommonOptionsInterface, ActionSheetAndroidOptionsInterface, ActionSheetOptionsInterface, } from './action-sheet-options.interface.js';
3
+ export declare const showActionSheetWithOptions: (options: ActionSheetOptionsInterface) => Promise<number | undefined>;
4
+ export declare const dismissActionSheet: () => void;
5
+ export declare const dismissAllActionSheets: () => void;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qCAAkC,CAAC;AAEpF,YAAY,EACV,0BAA0B,EAC1B,0BAA0B,EAC1B,iCAAiC,EACjC,kCAAkC,EAClC,2BAA2B,GAC5B,MAAM,qCAAkC,CAAC;AAsF1C,eAAO,MAAM,0BAA0B,GACrC,SAAS,2BAA2B,KACnC,OAAO,CAAC,MAAM,GAAG,SAAS,CAiB5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAAO,IAIrC,CAAC;AAIF,eAAO,MAAM,sBAAsB,QAAO,IAIzC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,155 @@
1
+ {
2
+ "name": "react-native-unified-action-sheet",
3
+ "version": "0.1.0",
4
+ "description": "Unified action sheet for React Native: a native UIAlertController on iOS, a native AppCompatDialog on Android",
5
+ "main": "./lib/commonjs/index.js",
6
+ "sideEffects": false,
7
+ "types": "./lib/typescript/commonjs/src/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "react-native-unified-action-sheet-source": "./src/index.tsx",
11
+ "import": {
12
+ "types": "./lib/typescript/module/src/index.d.ts",
13
+ "default": "./lib/module/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./lib/typescript/commonjs/src/index.d.ts",
17
+ "default": "./lib/commonjs/index.js"
18
+ }
19
+ },
20
+ "./package.json": "./package.json",
21
+ "./jest": {
22
+ "types": "./jest/index.d.ts",
23
+ "default": "./jest/index.js"
24
+ }
25
+ },
26
+ "files": [
27
+ "src",
28
+ "lib",
29
+ "jest",
30
+ "android",
31
+ "ios",
32
+ "*.podspec",
33
+ "CHANGELOG.md",
34
+ "!android/build",
35
+ "!android/gradle",
36
+ "!android/gradlew",
37
+ "!android/gradlew.bat",
38
+ "!android/local.properties",
39
+ "!**/__tests__",
40
+ "!**/__fixtures__",
41
+ "!**/__mocks__",
42
+ "!**/.*"
43
+ ],
44
+ "scripts": {
45
+ "example": "yarn workspace react-native-unified-action-sheet-example",
46
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
47
+ "prepare": "bob build",
48
+ "typecheck": "tsc",
49
+ "test": "jest",
50
+ "lint": "eslint \"**/*.{js,ts,tsx}\""
51
+ },
52
+ "keywords": [
53
+ "react-native",
54
+ "ios",
55
+ "android",
56
+ "action-sheet",
57
+ "actionsheet",
58
+ "action-sheet-ios",
59
+ "turbomodule"
60
+ ],
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "git+https://github.com/galikvalkin/react-native-unified-action-sheet.git"
64
+ },
65
+ "author": "Valentyn Halkin <galikvalkin@gmail.com> (https://github.com/galikvalkin)",
66
+ "license": "MIT",
67
+ "engines": {
68
+ "node": ">= 18"
69
+ },
70
+ "bugs": {
71
+ "url": "https://github.com/galikvalkin/react-native-unified-action-sheet/issues"
72
+ },
73
+ "homepage": "https://github.com/galikvalkin/react-native-unified-action-sheet#readme",
74
+ "publishConfig": {
75
+ "registry": "https://registry.npmjs.org/"
76
+ },
77
+ "devDependencies": {
78
+ "@eslint/compat": "^2.1.0",
79
+ "@eslint/eslintrc": "^3.3.5",
80
+ "@eslint/js": "^10.0.1",
81
+ "@jest/globals": "^30.4.1",
82
+ "@react-native/babel-preset": "0.85.0",
83
+ "@react-native/eslint-config": "0.85.0",
84
+ "@types/react": "^19.2.0",
85
+ "del-cli": "^7.0.0",
86
+ "eslint": "^9.39.4",
87
+ "eslint-config-prettier": "^10.1.8",
88
+ "eslint-plugin-ft-flow": "^3.0.11",
89
+ "eslint-plugin-prettier": "^5.5.6",
90
+ "jest": "^30.4.2",
91
+ "prettier": "^3.8.3",
92
+ "react": "19.2.3",
93
+ "react-native": "0.85.0",
94
+ "react-native-builder-bob": "^0.43.0",
95
+ "react-native-modal": "^14.0.0-rc.1",
96
+ "turbo": "^2.9.16",
97
+ "typescript": "^6.0.3"
98
+ },
99
+ "peerDependencies": {
100
+ "react": "*",
101
+ "react-native": ">=0.81.0"
102
+ },
103
+ "workspaces": [
104
+ "example"
105
+ ],
106
+ "packageManager": "yarn@4.11.0",
107
+ "react-native-builder-bob": {
108
+ "source": "src",
109
+ "output": "lib",
110
+ "targets": [
111
+ [
112
+ "commonjs",
113
+ {
114
+ "esm": true
115
+ }
116
+ ],
117
+ [
118
+ "module",
119
+ {
120
+ "esm": true
121
+ }
122
+ ],
123
+ [
124
+ "typescript",
125
+ {
126
+ "project": "tsconfig.build.json"
127
+ }
128
+ ]
129
+ ]
130
+ },
131
+ "codegenConfig": {
132
+ "name": "UnifiedActionSheetSpec",
133
+ "type": "modules",
134
+ "jsSrcsDir": "src",
135
+ "android": {
136
+ "javaPackageName": "com.unifiedactionsheet"
137
+ }
138
+ },
139
+ "prettier": {
140
+ "quoteProps": "consistent",
141
+ "singleQuote": true,
142
+ "tabWidth": 2,
143
+ "trailingComma": "es5",
144
+ "useTabs": false
145
+ },
146
+ "create-react-native-library": {
147
+ "type": "turbo-module",
148
+ "languages": "kotlin-objc",
149
+ "tools": [
150
+ "eslint"
151
+ ],
152
+ "version": "0.63.0"
153
+ },
154
+ "module": "./lib/module/index.js"
155
+ }
@@ -0,0 +1,23 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "react-native-unified-action-sheet"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.description = <<~DESC
10
+ One action-sheet API for both platforms, presented natively:
11
+ a UIAlertController on iOS and an AppCompatDialog on Android.
12
+ DESC
13
+ s.homepage = package["homepage"]
14
+ s.license = package["license"]
15
+ s.authors = package["author"]
16
+
17
+ s.platforms = { :ios => min_ios_version_supported }
18
+ s.source = { :git => "https://github.com/galikvalkin/react-native-unified-action-sheet.git", :tag => "v#{s.version}" }
19
+
20
+ s.source_files = "ios/**/*.{h,m,mm,swift}"
21
+
22
+ install_modules_dependencies(s)
23
+ end
@@ -0,0 +1,29 @@
1
+ import { TurboModuleRegistry, type TurboModule } from 'react-native';
2
+
3
+ export interface Spec extends TurboModule {
4
+ showActionSheetWithOptions(options: {
5
+ options: string[];
6
+ cancelButtonIndex?: number;
7
+ destructiveButtonIndices?: number[];
8
+ title?: string;
9
+ message?: string;
10
+ tintColor?: string;
11
+ cancelButtonTintColor?: string;
12
+ destructiveColor?: string;
13
+ buttonTextAlignment?: string;
14
+ disabledButtonIndices?: number[];
15
+ userInterfaceStyle?: string;
16
+ presentationStyle?: string;
17
+ anchorAlignment?: string;
18
+ anchorRect?: {
19
+ x: number;
20
+ y: number;
21
+ width: number;
22
+ height: number;
23
+ };
24
+ }): Promise<number>;
25
+ dismissActionSheet(): void;
26
+ dismissAllActionSheets(): void;
27
+ }
28
+
29
+ export default TurboModuleRegistry.getEnforcing<Spec>('UnifiedActionSheet');
@@ -0,0 +1,43 @@
1
+ /// One button. `style` mirrors React Native's own Alert API and the native
2
+ /// button roles, which are mutually exclusive; `disabled` is independent of it.
3
+ export interface ActionSheetButtonInterface {
4
+ label: string;
5
+ style?: 'cancel' | 'destructive';
6
+ disabled?: boolean;
7
+ /// Runs when this button resolves the sheet, so callers need not match on the
8
+ /// index. A dismissal that resolves the cancel button counts as pressing it.
9
+ onPress?: () => void;
10
+ }
11
+
12
+ /// Anything measurable — every React Native host component ref has this method,
13
+ /// so a `useRef` on a View, Pressable or Touchable satisfies it.
14
+ export interface ActionSheetAnchorInterface {
15
+ measureInWindow: (
16
+ callback: (x: number, y: number, width: number, height: number) => void
17
+ ) => void;
18
+ }
19
+
20
+ export interface ActionSheetCommonOptionsInterface {
21
+ options: ActionSheetButtonInterface[];
22
+ title?: string;
23
+ message?: string;
24
+ tintColor?: string;
25
+ cancelButtonTintColor?: string;
26
+ userInterfaceStyle?: 'light' | 'dark';
27
+ anchor?:
28
+ | ActionSheetAnchorInterface
29
+ | { current: ActionSheetAnchorInterface | null }
30
+ | null;
31
+ destructiveColor?: string;
32
+ presentationStyle?: 'centered' | 'anchored';
33
+ }
34
+
35
+ export interface ActionSheetAndroidOptionsInterface {
36
+ buttonTextAlignment?: 'start' | 'center';
37
+ anchorAlignment?: 'start' | 'center';
38
+ }
39
+
40
+ export interface ActionSheetOptionsInterface
41
+ extends
42
+ ActionSheetCommonOptionsInterface,
43
+ ActionSheetAndroidOptionsInterface {}
package/src/index.tsx ADDED
@@ -0,0 +1,131 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ import type { Spec } from './NativeUnifiedActionSheet';
4
+ import type { ActionSheetOptionsInterface } from './action-sheet-options.interface';
5
+
6
+ export type {
7
+ ActionSheetAnchorInterface,
8
+ ActionSheetButtonInterface,
9
+ ActionSheetCommonOptionsInterface,
10
+ ActionSheetAndroidOptionsInterface,
11
+ ActionSheetOptionsInterface,
12
+ } from './action-sheet-options.interface';
13
+
14
+ const DISMISSED_BY_API = -2;
15
+
16
+ /// The native wire format is index-based; the public API is not. Nothing below
17
+ /// index.tsx knows buttons are described as objects.
18
+ type WireOptions = Omit<ActionSheetOptionsInterface, 'options' | 'anchor'> & {
19
+ options: string[];
20
+ cancelButtonIndex?: number;
21
+ destructiveButtonIndices?: number[];
22
+ disabledButtonIndices?: number[];
23
+ anchorRect?: { x: number; y: number; width: number; height: number };
24
+ };
25
+
26
+ const nativeModule = (): Spec =>
27
+ require('./NativeUnifiedActionSheet').default as Spec;
28
+
29
+ /// Flattens the buttons into the labels and index sets the native side expects.
30
+ /// Only the first button styled 'cancel' counts, since there is one cancel row.
31
+ const toWireOptions = ({
32
+ options,
33
+ // Dropped deliberately: the anchor is a ref, and only its measured rect
34
+ // crosses the bridge. Omit<> would not strip it at runtime.
35
+ anchor: _anchor,
36
+ ...rest
37
+ }: ActionSheetOptionsInterface): WireOptions => {
38
+ const labels: string[] = [];
39
+ const destructive: number[] = [];
40
+ const disabled: number[] = [];
41
+ let cancelButtonIndex: number | undefined;
42
+
43
+ options.forEach((button, index) => {
44
+ labels.push(button.label);
45
+
46
+ if (button.style === 'destructive') destructive.push(index);
47
+ if (button.style === 'cancel' && cancelButtonIndex == null) {
48
+ cancelButtonIndex = index;
49
+ }
50
+ if (button.disabled) disabled.push(index);
51
+ });
52
+
53
+ return {
54
+ ...rest,
55
+ options: labels,
56
+ ...(cancelButtonIndex == null ? {} : { cancelButtonIndex }),
57
+ ...(destructive.length === 0
58
+ ? {}
59
+ : { destructiveButtonIndices: destructive }),
60
+ ...(disabled.length === 0 ? {} : { disabledButtonIndices: disabled }),
61
+ };
62
+ };
63
+
64
+ const showWithNativeModule = (
65
+ options: WireOptions
66
+ ): Promise<number | undefined> =>
67
+ nativeModule()
68
+ .showActionSheetWithOptions(options)
69
+ // A programmatic dismiss resolves with no index rather than a selection.
70
+ .then((buttonIndex) =>
71
+ buttonIndex === DISMISSED_BY_API ? undefined : buttonIndex
72
+ )
73
+ .catch(() => options.cancelButtonIndex ?? -1);
74
+
75
+ /// The anchor is measured in JS and sent across as a rect, so neither native
76
+ /// module has to resolve a view: a ref's own measureInWindow is the supported
77
+ /// way to do this on both architectures, unlike a react tag.
78
+ const withAnchorRect = (
79
+ wire: WireOptions,
80
+ anchor: ActionSheetOptionsInterface['anchor']
81
+ ): Promise<WireOptions> => {
82
+ const target =
83
+ anchor && 'measureInWindow' in anchor ? anchor : (anchor?.current ?? null);
84
+
85
+ if (!target) return Promise.resolve(wire);
86
+
87
+ return new Promise((resolve) => {
88
+ target.measureInWindow((x, y, width, height) => {
89
+ const measured = typeof x === 'number' && typeof y === 'number';
90
+
91
+ resolve(
92
+ measured ? { ...wire, anchorRect: { x, y, width, height } } : wire
93
+ );
94
+ });
95
+ });
96
+ };
97
+
98
+ export const showActionSheetWithOptions = (
99
+ options: ActionSheetOptionsInterface
100
+ ): Promise<number | undefined> => {
101
+ const wire = toWireOptions(options);
102
+
103
+ // -1 and undefined index nothing, so optional chaining covers both.
104
+ const press = (buttonIndex: number | undefined) => {
105
+ if (buttonIndex != null) options.options[buttonIndex]?.onPress?.();
106
+
107
+ return buttonIndex;
108
+ };
109
+
110
+ if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
111
+ return Promise.resolve(undefined);
112
+ }
113
+
114
+ return withAnchorRect(wire, options.anchor)
115
+ .then(showWithNativeModule)
116
+ .then(press);
117
+ };
118
+
119
+ export const dismissActionSheet = (): void => {
120
+ if (Platform.OS === 'ios' || Platform.OS === 'android') {
121
+ nativeModule().dismissActionSheet();
122
+ }
123
+ };
124
+
125
+ /// Closes every open sheet, not just the top-most one. Each resolves with no
126
+ /// index, exactly as dismissActionSheet() does.
127
+ export const dismissAllActionSheets = (): void => {
128
+ if (Platform.OS === 'ios' || Platform.OS === 'android') {
129
+ nativeModule().dismissAllActionSheets();
130
+ }
131
+ };