@niibase/bottom-sheet-manager 1.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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/lib/commonjs/events.js +35 -0
  4. package/lib/commonjs/events.js.map +1 -0
  5. package/lib/commonjs/index.js +85 -0
  6. package/lib/commonjs/index.js.map +1 -0
  7. package/lib/commonjs/manager.js +171 -0
  8. package/lib/commonjs/manager.js.map +1 -0
  9. package/lib/commonjs/provider.js +229 -0
  10. package/lib/commonjs/provider.js.map +1 -0
  11. package/lib/commonjs/router/index.js +100 -0
  12. package/lib/commonjs/router/index.js.map +1 -0
  13. package/lib/commonjs/router/router.js +72 -0
  14. package/lib/commonjs/router/router.js.map +1 -0
  15. package/lib/commonjs/router/types.js +6 -0
  16. package/lib/commonjs/router/types.js.map +1 -0
  17. package/lib/commonjs/router/view.js +180 -0
  18. package/lib/commonjs/router/view.js.map +1 -0
  19. package/lib/commonjs/sheet.js +240 -0
  20. package/lib/commonjs/sheet.js.map +1 -0
  21. package/lib/commonjs/types.js +6 -0
  22. package/lib/commonjs/types.js.map +1 -0
  23. package/lib/module/events.js +29 -0
  24. package/lib/module/events.js.map +1 -0
  25. package/lib/module/index.js +6 -0
  26. package/lib/module/index.js.map +1 -0
  27. package/lib/module/manager.js +165 -0
  28. package/lib/module/manager.js.map +1 -0
  29. package/lib/module/provider.js +210 -0
  30. package/lib/module/provider.js.map +1 -0
  31. package/lib/module/router/index.js +79 -0
  32. package/lib/module/router/index.js.map +1 -0
  33. package/lib/module/router/router.js +65 -0
  34. package/lib/module/router/router.js.map +1 -0
  35. package/lib/module/router/types.js +2 -0
  36. package/lib/module/router/types.js.map +1 -0
  37. package/lib/module/router/view.js +173 -0
  38. package/lib/module/router/view.js.map +1 -0
  39. package/lib/module/sheet.js +232 -0
  40. package/lib/module/sheet.js.map +1 -0
  41. package/lib/module/types.js +2 -0
  42. package/lib/module/types.js.map +1 -0
  43. package/lib/typescript/events.d.ts +16 -0
  44. package/lib/typescript/events.d.ts.map +1 -0
  45. package/lib/typescript/index.d.ts +6 -0
  46. package/lib/typescript/index.d.ts.map +1 -0
  47. package/lib/typescript/manager.d.ts +78 -0
  48. package/lib/typescript/manager.d.ts.map +1 -0
  49. package/lib/typescript/provider.d.ts +69 -0
  50. package/lib/typescript/provider.d.ts.map +1 -0
  51. package/lib/typescript/router/index.d.ts +59 -0
  52. package/lib/typescript/router/index.d.ts.map +1 -0
  53. package/lib/typescript/router/router.d.ts +47 -0
  54. package/lib/typescript/router/router.d.ts.map +1 -0
  55. package/lib/typescript/router/types.d.ts +46 -0
  56. package/lib/typescript/router/types.d.ts.map +1 -0
  57. package/lib/typescript/router/view.d.ts +11 -0
  58. package/lib/typescript/router/view.d.ts.map +1 -0
  59. package/lib/typescript/sheet.d.ts +19 -0
  60. package/lib/typescript/sheet.d.ts.map +1 -0
  61. package/lib/typescript/types.d.ts +125 -0
  62. package/lib/typescript/types.d.ts.map +1 -0
  63. package/package.json +102 -0
  64. package/src/events.ts +40 -0
  65. package/src/index.ts +11 -0
  66. package/src/manager.ts +223 -0
  67. package/src/provider.tsx +293 -0
  68. package/src/router/index.tsx +130 -0
  69. package/src/router/router.ts +94 -0
  70. package/src/router/types.ts +117 -0
  71. package/src/router/view.tsx +265 -0
  72. package/src/sheet.tsx +350 -0
  73. package/src/types.ts +153 -0
@@ -0,0 +1,19 @@
1
+ import { BottomSheetBackdrop, BottomSheetFlatList, BottomSheetFooter, BottomSheetFooterContainer, BottomSheetHandle, BottomSheetScrollView, BottomSheetSectionList, BottomSheetTextInput, BottomSheetView, BottomSheetVirtualizedList } from "@gorhom/bottom-sheet";
2
+ import React from "react";
3
+ import { BottomSheetInstance, BottomSheetProps, SheetIds } from "./types";
4
+ interface BottomSheetFC extends React.MemoExoticComponent<React.ForwardRefExoticComponent<BottomSheetProps>> {
5
+ <Id extends SheetIds>(props: BottomSheetProps & React.RefAttributes<BottomSheetInstance<Id>>): React.JSX.Element;
6
+ View: typeof BottomSheetView;
7
+ ScrollView: typeof BottomSheetScrollView;
8
+ FlatList: typeof BottomSheetFlatList;
9
+ SectionList: typeof BottomSheetSectionList;
10
+ VirtualizedList: typeof BottomSheetVirtualizedList;
11
+ Handle: typeof BottomSheetHandle;
12
+ Footer: typeof BottomSheetFooter;
13
+ FooterContainer: typeof BottomSheetFooterContainer;
14
+ Backdrop: typeof BottomSheetBackdrop;
15
+ TextInput: typeof BottomSheetTextInput;
16
+ }
17
+ declare const BottomSheet: BottomSheetFC;
18
+ export default BottomSheet;
19
+ //# sourceMappingURL=sheet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sheet.d.ts","sourceRoot":"","sources":["../../src/sheet.tsx"],"names":[],"mappings":"AAAA,OAAsB,EACpB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,0BAA0B,EAC1B,iBAAiB,EAEjB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,EACpB,eAAe,EACf,0BAA0B,EAC3B,MAAM,sBAAsB,CAAC;AAgB9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAQ1B,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAI1E,UAAU,aACR,SAAQ,KAAK,CAAC,mBAAmB,CAAC,KAAK,CAAC,yBAAyB,CAAC,gBAAgB,CAAC,CAAC;IACpF,CAAC,EAAE,SAAS,QAAQ,EAClB,KAAK,EAAE,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,GACrE,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;IAGrB,IAAI,EAAE,OAAO,eAAe,CAAC;IAC7B,UAAU,EAAE,OAAO,qBAAqB,CAAC;IACzC,QAAQ,EAAE,OAAO,mBAAmB,CAAC;IACrC,WAAW,EAAE,OAAO,sBAAsB,CAAC;IAC3C,eAAe,EAAE,OAAO,0BAA0B,CAAC;IACnD,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,eAAe,EAAE,OAAO,0BAA0B,CAAC;IACnD,QAAQ,EAAE,OAAO,mBAAmB,CAAC;IACrC,SAAS,EAAE,OAAO,oBAAoB,CAAC;CACxC;AAyQD,QAAA,MAAM,WAAW,EAAuC,aAAa,CAAC;AA2BtE,eAAe,WAAW,CAAC"}
@@ -0,0 +1,125 @@
1
+ import type { BottomSheetProps as RNBottomSheetProps } from "@gorhom/bottom-sheet";
2
+ import type { WithSpringConfig, WithTimingConfig } from "react-native-reanimated";
3
+ import React from "react";
4
+ export interface Sheets {
5
+ }
6
+ export type SheetIds = keyof Sheets;
7
+ export type SheetID<Id extends SheetIds> = Id | (string & {});
8
+ export type SheetPayload<Id extends SheetIds> = Sheets[Id]["payload"];
9
+ export type SheetReturnValue<Id extends SheetIds> = Sheets[Id]["returnValue"];
10
+ type AnimationConfigs = WithSpringConfig | WithTimingConfig;
11
+ export interface SheetProps<Id extends SheetIds = SheetIds> {
12
+ readonly id: SheetID<Id>;
13
+ readonly payload: SheetPayload<Id>;
14
+ readonly context: string;
15
+ }
16
+ export interface SheetDefinition<Payload = never, ReturnValue = never> {
17
+ payload: Payload;
18
+ returnValue: ReturnValue;
19
+ }
20
+ export interface BottomSheetInstance<Id extends SheetIds = SheetIds> {
21
+ /**
22
+ * Close the bottom sheet.
23
+ * @param args
24
+ */
25
+ readonly close: (...args: SheetReturnValue<Id> extends never ? [
26
+ options?: {
27
+ /**
28
+ * Snap animation configs.
29
+ */
30
+ animationConfigs?: AnimationConfigs;
31
+ }
32
+ ] : [
33
+ options: {
34
+ /**
35
+ * Return some data to the caller on closing the `BottomSheet`.
36
+ */
37
+ value: SheetReturnValue<Id>;
38
+ /**
39
+ * Snap animation configs.
40
+ */
41
+ animationConfigs?: AnimationConfigs;
42
+ }
43
+ ]) => void;
44
+ /**
45
+ * Snap to the maximum provided point from `snapPoints`.
46
+ * @param animationConfigs Snap animation configs.
47
+ */
48
+ readonly expand: (animationConfigs?: AnimationConfigs) => void;
49
+ /**
50
+ * Snap to the minimum provided point from `snapPoints`.
51
+ * @param animationConfigs Snap animation configs.
52
+ */
53
+ readonly collapse: (animationConfigs?: AnimationConfigs) => void;
54
+ /**
55
+ * Snap to one of the provided points from `snapPoints`.
56
+ * @param index Snap point index.
57
+ * @param animationConfigs Snap animation configs.
58
+ */
59
+ readonly snapToIndex: (index: number, animationConfigs?: AnimationConfigs) => void;
60
+ /**
61
+ * Snap to a position out of provided `snapPoints`.
62
+ * @param position Position in pixel or percentage.
63
+ * @param animationConfigs Snap animation configs.
64
+ */
65
+ readonly snapToPosition: (position: string | number, animationConfigs?: AnimationConfigs) => void;
66
+ }
67
+ export type BottomSheetProps = Omit<RNBottomSheetProps, "children" | "onClose" | "animatedIndex" | "topInset"> & {
68
+ /**
69
+ * ID of the `BottomSheet`.
70
+ */
71
+ id?: SheetID<SheetIds>;
72
+ /**
73
+ * Content of the `BottomSheet`.
74
+ */
75
+ children: React.ReactNode;
76
+ /**
77
+ * When set to true, `BottomSheet` is closed when the hardware back button is pressed.
78
+ * @default true
79
+ */
80
+ hardwareBackPressToClose?: boolean;
81
+ /**
82
+ * Callback when the sheet close.
83
+ *
84
+ * @type () => void;
85
+ */
86
+ onClose?: (data?: any) => void;
87
+ /**
88
+ * Event called before sheets is visible.
89
+ * @param data Payload of the sheet if any.
90
+ * @type () => void;
91
+ */
92
+ onBeforeShow?: (data?: any) => void;
93
+ /**
94
+ * Can click through the sheet to the underlying view.
95
+ * @default false
96
+ */
97
+ clickThrough?: boolean;
98
+ /**
99
+ * Opacity of the sheet's overlay.
100
+ * @default 0.45
101
+ */
102
+ opacity?: number;
103
+ /**
104
+ * Defines the stack behavior when modal mounts. (experimental)
105
+ * @default "switch"
106
+ */
107
+ stackBehavior?: "push" | "replace" | "switch";
108
+ /**
109
+ * Whether the bottom sheet edge to edge.
110
+ * @default false
111
+ */
112
+ fullScreen?: boolean;
113
+ /**
114
+ * Whether the bottom sheet is an iOS modal sheet type of animation.
115
+ * @default false
116
+ */
117
+ iosModalSheetTypeOfAnimation?: boolean;
118
+ className?: string;
119
+ handleIndicatorClassName?: string;
120
+ backgroundClassName?: string;
121
+ containerClassName?: string;
122
+ handleClassName?: string;
123
+ };
124
+ export {};
125
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "name": "@niibase/bottom-sheet-manager",
3
+ "version": "1.1.0",
4
+ "description": "A bottom sheet manager for react-native based on @gorhom/bottom-sheet",
5
+ "main": "lib/commonjs/index",
6
+ "module": "lib/module/index",
7
+ "types": "lib/typescript/index.d.ts",
8
+ "react-native": "src/index.ts",
9
+ "source": "src/index.ts",
10
+ "scripts": {
11
+ "typescript": "tsc --skipLibCheck --noEmit",
12
+ "lint": "prettier --check \"src/**/*\" \"example/**/*\"",
13
+ "format": "prettier --write \"src/**/*\" \"example/**/*\"",
14
+ "build": "bob build && yarn copy-dts && yarn delete-dts.js",
15
+ "copy-dts": "copyfiles -u 1 \"src/**/*.d.ts\" lib/typescript",
16
+ "delete-dts.js": "find ./lib/commonjs -name '*.d.js*' -delete && find ./lib/module -name '*.d.js*' -delete",
17
+ "release": "rm -rf lib && yarn build && release-it",
18
+ "example": "yarn --cwd example",
19
+ "bootstrap": "yarn install && yarn example"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/divineniiquaye/react-native-bottom-sheet-manager.git"
24
+ },
25
+ "keywords": [
26
+ "react-native",
27
+ "ios",
28
+ "android",
29
+ "web",
30
+ "bottom-sheet-manager",
31
+ "bottom-sheet",
32
+ "bottomsheet",
33
+ "reanimated",
34
+ "sheet"
35
+ ],
36
+ "author": "Divine Niiquaye Ibok",
37
+ "license": "MIT",
38
+ "bugs": {
39
+ "url": "https://github.com/divineniiquaye/react-native-bottom-sheet-manager/issues"
40
+ },
41
+ "homepage": "https://github.com/divineniiquaye/react-native-bottom-sheet-manager#readme",
42
+ "publishConfig": {
43
+ "registry": "https://registry.npmjs.org/",
44
+ "access": "public"
45
+ },
46
+ "files": [
47
+ "src",
48
+ "lib",
49
+ "LICENSE"
50
+ ],
51
+ "peerDependencies": {
52
+ "@react-navigation/native": ">=6.0.0 || >=7.0.0-",
53
+ "@types/react": "*",
54
+ "@types/react-native": "*",
55
+ "react": "*",
56
+ "react-native": "*",
57
+ "react-native-gesture-handler": ">=2.16.1",
58
+ "react-native-reanimated": ">=3.16.0 || >=4.0.0-",
59
+ "react-native-safe-area-context": "*"
60
+ },
61
+ "peerDependenciesMeta": {
62
+ "@types/react-native": {
63
+ "optional": true
64
+ },
65
+ "@types/react": {
66
+ "optional": true
67
+ }
68
+ },
69
+ "dependencies": {
70
+ "@gorhom/bottom-sheet": "^5.2.6",
71
+ "nanoid": "^5.1.6"
72
+ },
73
+ "devDependencies": {
74
+ "@commitlint/cli": "^19.8.1",
75
+ "@commitlint/config-conventional": "^19.8.1",
76
+ "@ianvs/prettier-plugin-sort-imports": "file:patched/prettier-plugin-sort-imports",
77
+ "@react-navigation/native": "^7.1.9",
78
+ "@release-it/conventional-changelog": "^10.0.1",
79
+ "@types/react": "~18.3.12",
80
+ "@types/react-native": "~0.73.0",
81
+ "copyfiles": "^2.4.1",
82
+ "metro-react-native-babel-preset": "^0.77.0",
83
+ "prettier": "3.6.2",
84
+ "react": "18.3.1",
85
+ "react-native": "0.76.0",
86
+ "react-native-builder-bob": "^0.23.2",
87
+ "react-native-gesture-handler": "~2.20.2",
88
+ "react-native-reanimated": "~3.19.1",
89
+ "react-native-safe-area-context": "~5.6.0",
90
+ "release-it": "^19.0.4",
91
+ "typescript": "^5.8.3"
92
+ },
93
+ "react-native-builder-bob": {
94
+ "source": "src",
95
+ "output": "lib",
96
+ "targets": [
97
+ "commonjs",
98
+ "module",
99
+ "typescript"
100
+ ]
101
+ }
102
+ }
package/src/events.ts ADDED
@@ -0,0 +1,40 @@
1
+ import {
2
+ DeviceEventEmitter,
3
+ NativeAppEventEmitter,
4
+ NativeEventEmitter,
5
+ Platform,
6
+ } from "react-native";
7
+
8
+ /* eslint-disable curly */
9
+ export type EventHandler = (...args: any[]) => void;
10
+ export type EventHandlerSubscription = {
11
+ unsubscribe: () => void;
12
+ };
13
+
14
+ export default class EventManager {
15
+ _registry?: NativeEventEmitter;
16
+ constructor() {
17
+ this._registry = Platform.select({
18
+ ios: NativeAppEventEmitter,
19
+ android: DeviceEventEmitter,
20
+ });
21
+ }
22
+
23
+ subscribe(name: string, handler: EventHandler) {
24
+ if (!name || !handler) throw new Error("name and handler are required.");
25
+ const event = this._registry?.addListener(name, handler);
26
+ return { unsubscribe: () => event?.remove() };
27
+ }
28
+
29
+ publish(name: string, ...args: any[]) {
30
+ this._registry?.emit(name, ...args);
31
+ }
32
+
33
+ remove(...names: string[]) {
34
+ for (const eventType of names) {
35
+ this._registry?.removeAllListeners(eventType);
36
+ }
37
+ }
38
+ }
39
+
40
+ export const eventManager = new EventManager();
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ export { default as BottomSheet } from "./sheet";
2
+ export { SheetManager } from "./manager";
3
+ export * from "./router";
4
+ export * from "./types";
5
+ export {
6
+ SheetProvider,
7
+ useSheetPayload,
8
+ useSheetRef,
9
+ useOnSheet,
10
+ registerSheet,
11
+ } from "./provider";
package/src/manager.ts ADDED
@@ -0,0 +1,223 @@
1
+ import { RefObject } from "react";
2
+
3
+ import { eventManager } from "./events";
4
+ import { providerRegistryStack, sheetsRegistry } from "./provider";
5
+ import { BottomSheetInstance, Sheets } from "./types";
6
+
7
+ // Array of all the ids of Sheets currently rendered in the app.
8
+ const ids: string[] = [];
9
+ const keys: string[] = [];
10
+ const refs: { [name: string]: RefObject<BottomSheetInstance> } = {};
11
+ const DEFAULT_Z_INDEX = 999;
12
+
13
+ const makeKey = (id: string, context: string) => `${id}:${context}`;
14
+
15
+ export const PrivateManager = {
16
+ // Return to the previous sheet when the current sheet is closed.
17
+ history: [] as { id: string; context: string }[],
18
+
19
+ context(options?: { context?: string; id?: string }) {
20
+ if (!options) options = {};
21
+ if (!options?.context) {
22
+ // If no context is provided, use to current top most context
23
+ // to render the sheet.
24
+ for (const context of providerRegistryStack.slice().reverse()) {
25
+ // We only automatically select nested sheet providers.
26
+ if (
27
+ context.startsWith("$$-auto") &&
28
+ !context.includes(options?.id as string)
29
+ ) {
30
+ options.context = context;
31
+ break;
32
+ }
33
+ }
34
+ }
35
+ return options.context;
36
+ },
37
+
38
+ registerRef: (
39
+ id: string,
40
+ context: string,
41
+ instance: RefObject<BottomSheetInstance>,
42
+ ) => {
43
+ const key = makeKey(id, context);
44
+ refs[key] = instance;
45
+ keys.push(key);
46
+ },
47
+
48
+ /**
49
+ *
50
+ * Get internal ref of a sheet by the given id.
51
+ *
52
+ * @param id Id of the sheet
53
+ * @param context Context in which the sheet is rendered. Normally this function returns the top most rendered sheet ref automatically.
54
+ */
55
+ get: <SheetId extends keyof Sheets>(
56
+ id: SheetId | (string & {}),
57
+ context?: string,
58
+ ): RefObject<BottomSheetInstance<SheetId>> => {
59
+ if (!context) {
60
+ for (let ctx of providerRegistryStack.slice().reverse()) {
61
+ for (let _id in sheetsRegistry[ctx]) {
62
+ if (_id === id) {
63
+ context = ctx;
64
+ break;
65
+ }
66
+ }
67
+ }
68
+ }
69
+ return refs[makeKey(id, context!)] as RefObject<BottomSheetInstance<SheetId>>;
70
+ },
71
+
72
+ add: (id: string, context: string) => {
73
+ if (ids.indexOf(id) < 0) {
74
+ ids[ids.length] = makeKey(id, context);
75
+ }
76
+ },
77
+
78
+ remove: (id: string, context: string) => {
79
+ if (ids.indexOf(makeKey(id, context)) > -1) {
80
+ ids.splice(ids.indexOf(makeKey(id, context)));
81
+ }
82
+ },
83
+
84
+ zIndex: (id: string, context: string = "global"): number => {
85
+ const index = keys.indexOf(makeKey(id, context));
86
+ return index > -1 ? DEFAULT_Z_INDEX + index + 1 : DEFAULT_Z_INDEX;
87
+ },
88
+
89
+ stack: () =>
90
+ ids.map((id) => {
91
+ return {
92
+ id: id.split(":")[0],
93
+ context: id.split(":")?.[1] || "global",
94
+ };
95
+ }),
96
+ };
97
+
98
+ class _SheetManager {
99
+ /**
100
+ * Show the Modal Sheet with an id.
101
+ *
102
+ * @param id id of the Sheet to show
103
+ * @param options
104
+ */
105
+ async show<SheetId extends keyof Sheets>(
106
+ id: SheetId | (string & {}),
107
+ options?: {
108
+ /**
109
+ * Any data to pass to the Sheet. Will be available from the component `props` prop on the modal sheet.
110
+ */
111
+ payload?: Sheets[SheetId]["payload"];
112
+
113
+ /**
114
+ * Receive payload from the Sheet when it closes
115
+ */
116
+ onClose?: (data: Sheets[SheetId]["returnValue"] | undefined) => void;
117
+
118
+ /**
119
+ * Provide `context` of the `SheetProvider` where you want to show the action sheet.
120
+ */
121
+ context?: string;
122
+ },
123
+ ): Promise<Sheets[SheetId]["returnValue"]> {
124
+ return new Promise((resolve) => {
125
+ const currentContext = PrivateManager.context({ ...options, id: id });
126
+ const handler = (data: any, context = "global") => {
127
+ if (context !== "global" && currentContext && currentContext !== context)
128
+ return;
129
+ options?.onClose?.(data);
130
+ sub?.unsubscribe();
131
+ resolve(data);
132
+ };
133
+
134
+ var sub = eventManager.subscribe(`onclose_${id}`, handler);
135
+ PrivateManager.stack().forEach(({ id, context }) => {
136
+ eventManager.publish(`hide_${id}`, undefined, context, true);
137
+ });
138
+
139
+ // Check if the sheet is registered with any `SheetProviders`.
140
+ let isRegisteredWithSheetProvider = false;
141
+ for (let ctx in sheetsRegistry) {
142
+ for (let _id in sheetsRegistry[ctx]) {
143
+ if (_id === id) {
144
+ isRegisteredWithSheetProvider = true;
145
+ }
146
+ }
147
+ }
148
+ eventManager.publish(
149
+ isRegisteredWithSheetProvider ? `show_wrap_${id}` : `show_${id}`,
150
+ options?.payload,
151
+ currentContext || "global",
152
+ );
153
+ });
154
+ }
155
+
156
+ /**
157
+ * An async hide function. This is useful when you want to show one Sheet after closing another.
158
+ *
159
+ * @param id id of the Sheet to show
160
+ * @param data
161
+ */
162
+ async hide<SheetId extends keyof Sheets>(
163
+ id: SheetId | (string & {}),
164
+ options?: {
165
+ /**
166
+ * Return some data to the caller on closing the Sheet.
167
+ */
168
+ payload?: Sheets[SheetId]["returnValue"];
169
+ /**
170
+ * Provide `context` of the `SheetProvider` to hide the action sheet.
171
+ */
172
+ context?: string;
173
+ },
174
+ ): Promise<Sheets[SheetId]["returnValue"]> {
175
+ let currentContext = PrivateManager.context({
176
+ ...options,
177
+ id: id,
178
+ });
179
+ return new Promise((resolve) => {
180
+ let isRegisteredWithSheetProvider = false;
181
+ // Check if the sheet is registered with any `SheetProviders`
182
+ // and select the nearest context where sheet is registered.
183
+
184
+ for (const _id of ids) {
185
+ if (_id === `${id}:${currentContext}`) {
186
+ isRegisteredWithSheetProvider = true;
187
+ break;
188
+ }
189
+ }
190
+
191
+ const hideHandler = (data: any, context = "global") => {
192
+ if (context !== "global" && currentContext && currentContext !== context)
193
+ return;
194
+ sub?.unsubscribe();
195
+ resolve(data);
196
+ };
197
+
198
+ var sub = eventManager.subscribe(`onclose_${id}`, hideHandler);
199
+ eventManager.publish(
200
+ isRegisteredWithSheetProvider ? `hide_wrap_${id}` : `hide_${id}`,
201
+ options?.payload,
202
+ !isRegisteredWithSheetProvider ? "global" : currentContext,
203
+ );
204
+ });
205
+ }
206
+
207
+ /**
208
+ * Hide all the opened Sheets.
209
+ *
210
+ * @param id Hide all sheets for the specific id.
211
+ */
212
+ hideAll<SheetId extends keyof Sheets>(id?: SheetId | (string & {})) {
213
+ PrivateManager.stack().forEach(({ id: _id, context }) => {
214
+ if (id && !_id.startsWith(id)) return;
215
+ eventManager.publish(`hide_${_id}`, undefined, context);
216
+ });
217
+ }
218
+ }
219
+
220
+ /**
221
+ * SheetManager is used to imperatively show/hide any sheet with a unique id prop.
222
+ */
223
+ export const SheetManager = new _SheetManager();