react-native-actions-sheet
Version:
A Cross Platform(Android & iOS) ActionSheet with a robust and flexible api, native performance and zero dependency code for react native. Create anything you want inside ActionSheet.
166 lines (162 loc) • 6.14 kB
JavaScript
/* eslint-disable curly */
import React, { createContext, useContext, useEffect, useReducer, useRef, useState, } from 'react';
import { actionSheetEventManager } from './eventmanager';
export var providerRegistryStack = [];
/**
* An object that holds all the sheet components against their ids.
*/
export var sheetsRegistry = {
global: {},
};
// Registers your Sheet with the SheetProvider.
export function registerSheet(id, Sheet) {
var contexts = [];
for (var _i = 2; _i < arguments.length; _i++) {
contexts[_i - 2] = arguments[_i];
}
if (!id || !Sheet)
return;
if (!contexts || contexts.length === 0)
contexts = ['global'];
for (var _a = 0, contexts_1 = contexts; _a < contexts_1.length; _a++) {
var context = contexts_1[_a];
var registry = !sheetsRegistry[context]
? (sheetsRegistry[context] = {})
: sheetsRegistry[context];
registry[id] = Sheet;
actionSheetEventManager.publish("".concat(context, "-on-register"));
}
}
/**
* The SheetProvider makes available the sheets in a given context. The default context is
* `global`. However if you want to render a Sheet within another sheet or if you want to render
* Sheets in a modal. You can use a seperate Provider with a custom context value.
*
* For example
```ts
// Define your SheetProvider in the component/modal where
// you want to show some Sheets.
<SheetProvider context="local-context" />
// Then register your sheet when for example the
// Modal component renders.
registerSheet('local-sheet', LocalSheet,'local-context');
```
* @returns
*/
export function SheetProvider(_a) {
var _b = _a.context, context = _b === void 0 ? 'global' : _b, children = _a.children;
var _c = useReducer(function (x) { return x + 1; }, 0), forceUpdate = _c[1];
var sheetIds = Object.keys(sheetsRegistry[context] || sheetsRegistry['global'] || {});
var onRegister = React.useCallback(function () {
// Rerender when a new sheet is added.
forceUpdate();
}, [forceUpdate]);
useEffect(function () {
providerRegistryStack.indexOf(context) > -1
? providerRegistryStack.indexOf(context)
: providerRegistryStack.push(context) - 1;
var unsub = actionSheetEventManager.subscribe("".concat(context, "-on-register"), onRegister);
return function () {
providerRegistryStack.splice(providerRegistryStack.indexOf(context), 1);
unsub === null || unsub === void 0 ? void 0 : unsub.unsubscribe();
};
}, [context, onRegister]);
var renderSheet = function (sheetId) { return (<RenderSheet key={sheetId} id={sheetId} context={context}/>); };
return (<>
{children}
{sheetIds.map(renderSheet)}
</>);
}
var ProviderContext = createContext('global');
var SheetIDContext = createContext(undefined);
export var SheetRefContext = createContext({});
var SheetPayloadContext = createContext(undefined);
/**
* Get id of the current context.
*/
export var useProviderContext = function () { return useContext(ProviderContext); };
/**
* Get id of the current sheet
*/
export var useSheetIDContext = function () { return useContext(SheetIDContext); };
/**
* Get the current Sheet's internal ref.
* @returns
*/
// export const useSheetRef = <SheetId extends keyof Sheets = never>(): RefObject<
// ActionSheetRef<SheetId>
// > => useContext(SheetRefContext) as RefObject<
// ActionSheetRef<SheetId>
// >;
export function useSheetRef(
//@ts-ignore
id) {
return useContext(SheetRefContext);
}
/**
* Get the payload this sheet was opened with.
* @returns
*/
export function useSheetPayload(
//@ts-ignore
id) {
return useContext(SheetPayloadContext);
}
var RenderSheet = function (_a) {
var _b, _c;
var id = _a.id, context = _a.context;
var _d = useState(), payload = _d[0], setPayload = _d[1];
var _e = useState(false), visible = _e[0], setVisible = _e[1];
var ref = useRef(null);
var Sheet = context.startsWith('$$-auto-')
? (_b = sheetsRegistry === null || sheetsRegistry === void 0 ? void 0 : sheetsRegistry.global) === null || _b === void 0 ? void 0 : _b[id]
: sheetsRegistry[context]
? (_c = sheetsRegistry[context]) === null || _c === void 0 ? void 0 : _c[id]
: undefined;
var onShow = React.useCallback(function (data, ctx) {
if (ctx === void 0) { ctx = 'global'; }
if (ctx !== context)
return;
setPayload(data);
setVisible(true);
}, [context]);
var onClose = React.useCallback(function (_data, ctx) {
if (ctx === void 0) { ctx = 'global'; }
if (context !== ctx)
return;
setVisible(false);
setTimeout(function () {
setPayload(undefined);
}, 1);
}, [context]);
var onHide = React.useCallback(function (data, ctx) {
if (ctx === void 0) { ctx = 'global'; }
actionSheetEventManager.publish("hide_".concat(id), data, ctx);
}, [id]);
useEffect(function () {
if (visible) {
actionSheetEventManager.publish("show_".concat(id), payload, context);
}
}, [context, id, payload, visible]);
useEffect(function () {
var subs = [
actionSheetEventManager.subscribe("show_wrap_".concat(id), onShow),
actionSheetEventManager.subscribe("onclose_".concat(id), onClose),
actionSheetEventManager.subscribe("hide_wrap_".concat(id), onHide),
];
return function () {
subs.forEach(function (s) { return s.unsubscribe(); });
};
}, [id, context, onShow, onHide, onClose]);
if (!Sheet)
return null;
return !visible ? null : (<ProviderContext.Provider value={context}>
<SheetIDContext.Provider value={id}>
<SheetRefContext.Provider value={ref}>
<SheetPayloadContext.Provider value={payload}>
<Sheet sheetId={id} payload={payload}/>
</SheetPayloadContext.Provider>
</SheetRefContext.Provider>
</SheetIDContext.Provider>
</ProviderContext.Provider>);
};