@mbrain/epic-react-native-lib 0.0.5 → 0.0.7

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/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var V=Object.create;var u=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var M=Object.getPrototypeOf,E=Object.prototype.hasOwnProperty;var A=(e,t)=>{for(var n in t)u(e,n,{get:t[n],enumerable:!0})},g=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of C(t))!E.call(e,a)&&a!==n&&u(e,a,{get:()=>t[a],enumerable:!(o=w(t,a))||o.enumerable});return e};var m=(e,t,n)=>(n=e!=null?V(M(e)):{},g(t||!e||!e.__esModule?u(n,"default",{value:e,enumerable:!0}):n,e)),b=e=>g(u({},"__esModule",{value:!0}),e);var P={};A(P,{Box1:()=>d,createLocalStorage:()=>L,useLogRouteChange:()=>k,useOrientation:()=>p});module.exports=b(P);var S=m(require("react"),1),c=require("react-native");function d({style:e,children:t}){let[n,o]=(0,S.useState)(0);return S.default.createElement(c.View,{style:e},S.default.createElement(c.Text,{style:N.text,onPress:()=>{o(a=>a+1)}},"Box1 ",n),t)}var N=c.StyleSheet.create({text:{fontSize:20,padding:15,borderRadius:10,color:"#ffffff",backgroundColor:"#0a234a"}});var f=require("react"),s=m(require("expo-screen-orientation"),1);function p(){let[e,t]=(0,f.useState)({orientation:void 0,orientationLock:void 0});return(0,f.useEffect)(()=>{Promise.all([s.getOrientationAsync(),s.getOrientationLockAsync()]).then(([o,a])=>{t({orientation:o,orientationLock:a})});let n=s.addOrientationChangeListener(o=>{t({orientation:o.orientationInfo.orientation,orientationLock:o.orientationLock})});return()=>n.remove()},[]),e}var h=require("react"),y=require("react-native-mmkv");function L({defaults:e,storage:t=(0,y.createMMKV)()}){let n=r=>{try{let i=t.getString(String(r));return i!==void 0?JSON.parse(i):e[r]}catch(i){return console.warn(i),e[r]}};return{useLocalStorage:r=>{let[i,l]=(0,h.useState)(()=>n(r));return(0,y.useMMKVListener)(v=>{String(r)===v&&l(n(r))},t),i},setLocalStorage:(r,i)=>{try{let l=JSON.stringify(i);t.set(String(r),l)}catch(l){console.warn(l)}},getLocalStorage:r=>n(r),removeLocalStorage:r=>{try{t.remove(String(r))}catch(i){console.warn(i)}},clearAllLocalStorage:()=>{try{t.clearAll()}catch(r){console.warn(r)}},storage:t}}var x=m(require("react"),1),K=require("expo-router"),O=m(require("lodash/isEmpty"),1);function k(){let e=(0,K.useNavigationContainerRef)();x.default.useEffect(()=>{if(__DEV__)return e.addListener("state",()=>{let n=e.getState(),o=R(n);o&&((0,O.default)(o.params)?console.log(`ROUTE CHANGED : ${o.name}`):console.log(`ROUTE CHANGED : ${o.name}`,o.params))})},[e])}function R(e){var t;if(!e)return null;if(e.routes&&e.routes.length>0){let n=(t=e.index)!=null?t:0,o=e.routes[n];if(!o)return null;if(o.state){let a=R(o.state);if(a)return a}return{name:o.name,params:o.params}}return null}
1
+ "use strict";var ie=Object.create;var k=Object.defineProperty;var se=Object.getOwnPropertyDescriptor;var ce=Object.getOwnPropertyNames;var le=Object.getPrototypeOf,de=Object.prototype.hasOwnProperty;var me=(e,t)=>{for(var r in t)k(e,r,{get:t[r],enumerable:!0})},A=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of ce(t))!de.call(e,n)&&n!==r&&k(e,n,{get:()=>t[n],enumerable:!(o=se(t,n))||o.enumerable});return e};var d=(e,t,r)=>(r=e!=null?ie(le(e)):{},A(t||!e||!e.__esModule?k(r,"default",{value:e,enumerable:!0}):r,e)),ue=e=>A(k({},"__esModule",{value:!0}),e);var fe={};me(fe,{Box1:()=>B,ScreenContent:()=>X,createLocalStorage:()=>$,useAndroidNavigationBar:()=>H,useLogRouteChange:()=>G,useOrientation:()=>E,useThemeNativewind4:()=>te});module.exports=ue(fe);var h=d(require("react"),1),S=require("react-native");function B({style:e,children:t}){let[r,o]=(0,h.useState)(0);return h.default.createElement(S.View,{style:e},h.default.createElement(S.Text,{style:pe.text,onPress:()=>{o(n=>n+1)}},"Box1 ",r),t)}var pe=S.StyleSheet.create({text:{fontSize:20,padding:15,borderRadius:10,color:"#ffffff",backgroundColor:"#0a234a"}});var x=require("react"),y=d(require("expo-screen-orientation"),1);function E(){let[e,t]=(0,x.useState)({orientation:void 0,orientationLock:void 0});return(0,x.useEffect)(()=>{Promise.all([y.getOrientationAsync(),y.getOrientationLockAsync()]).then(([o,n])=>{t({orientation:o,orientationLock:n})});let r=y.addOrientationChangeListener(o=>{t({orientation:o.orientationInfo.orientation,orientationLock:o.orientationLock})});return()=>r.remove()},[]),e}var M=d(require("react"),1),C=require("react-native"),m=d(require("expo-navigation-bar"),1);function H(e){let t=(0,C.useColorScheme)();M.default.useEffect(()=>{if(C.Platform.OS!=="android")return;m.setStyle(t==="dark"?"dark":"light");let r=t==="dark"?e==null?void 0:e.dark:e==null?void 0:e.light;if(!r)return;(async()=>{let n=[];r.backgroundColor&&(m.setBackgroundColorAsync(r.backgroundColor),n.push(m.setBackgroundColorAsync(r.backgroundColor))),r.borderColor&&n.push(m.setBorderColorAsync(r.borderColor)),n.length&&await Promise.all(n)})()},[t,e==null?void 0:e.dark,e==null?void 0:e.light])}var F=require("react"),b=require("react-native-mmkv");function $({defaults:e,storage:t=(0,b.createMMKV)()}){let r=a=>{try{let i=t.getString(String(a));return i!==void 0?JSON.parse(i):e[a]}catch(i){return console.warn(i),e[a]}};return{useLocalStorage:a=>{let[i,l]=(0,F.useState)(()=>r(a));return(0,b.useMMKVListener)(T=>{String(a)===T&&l(r(a))},t),i},setLocalStorage:(a,i)=>{try{let l=JSON.stringify(i);t.set(String(a),l)}catch(l){console.warn(l)}},getLocalStorage:a=>r(a),removeLocalStorage:a=>{try{t.remove(String(a))}catch(i){console.warn(i)}},clearAllLocalStorage:()=>{try{t.clearAll()}catch(a){console.warn(a)}},storage:t}}var j=d(require("react"),1),D=require("expo-router"),I=d(require("lodash/isEmpty"),1);function G(){let e=(0,D.useNavigationContainerRef)();j.default.useEffect(()=>{if(__DEV__)return e.addListener("state",()=>{let r=e.getState(),o=_(r);o&&((0,I.default)(o.params)?console.log(`ROUTE CHANGED : ${o.name}`):console.log(`ROUTE CHANGED : ${o.name}`,o.params))})},[e])}function _(e){var t;if(!e)return null;if(e.routes&&e.routes.length>0){let r=(t=e.index)!=null?t:0,o=e.routes[r];if(!o)return null;if(o.state){let n=_(o.state);if(n)return n}return{name:o.name,params:o.params}}return null}var u=d(require("react"),1),p=require("react-native"),W=require("nativewind"),q=require("react-native-safe-area-context"),Q=require("react-native-keyboard-controller");var g=d(require("react"),1),V=require("react-native"),P=require("@react-navigation/elements");function w(e){return(0,g.useMemo)(()=>e?typeof e=="function"?g.default.createElement(e,null):e:null,[e])}function J(e,t){let r=(0,P.useHeaderHeight)();return(0,g.useMemo)(()=>{let o=V.StyleSheet.flatten(e),n=o==null?void 0:o.padding,c=o==null?void 0:o.paddingTop,s=typeof c=="number"?c:typeof n=="number"?n:0;return t&&(s+=r),[z.flex,e,{paddingTop:s}]},[r,t,e])}function U(e,t){let r=(0,P.useHeaderHeight)();return(0,g.useMemo)(()=>{let o=V.StyleSheet.flatten(e),n=o==null?void 0:o.padding,c=o==null?void 0:o.paddingTop,s=typeof c=="number"?c:typeof n=="number"?n:0;return t&&(s+=r),[z.scrollContentStyle,e,{paddingTop:s}]},[e,r,t])}var z=V.StyleSheet.create({flex:{flex:1},scrollContentStyle:{flexGrow:1}});var Se=u.default.memo(function({scroll:t=!1,edges:r=[],headerTransparent:o=!1,scrollViewProps:n,scrollRef:c,style:s={},contentContainerStyle:f={},HeaderComponent:a,FooterComponent:i,BackgroundComponent:l,children:T}){let oe=J(s,o),re=U(f,o),ne=w(a),ae=w(i),O=w(l);return u.default.createElement(p.View,{style:R.flex},O&&u.default.createElement(p.View,{style:R.background},O),u.default.createElement(q.SafeAreaView,{edges:r,style:R.flex},ne,t&&u.default.createElement(Q.KeyboardAwareScrollView,{ref:c,enabled:!0,scrollEnabled:!0,style:[R.flex,s],contentContainerStyle:re,bottomOffset:40,disableScrollOnKeyboardHide:!0,keyboardShouldPersistTaps:"handled",showsVerticalScrollIndicator:!1,...n},T),!t&&u.default.createElement(p.View,{style:[{overflow:"hidden"},oe]},T),ae))}),R=p.StyleSheet.create({flex:{flex:1},background:{alignItems:"stretch",pointerEvents:"none",...p.StyleSheet.absoluteFill}}),X=(0,W.cssInterop)(Se,{className:"style",contentContainerClassName:"contentContainerStyle"});var L=d(require("react"),1),N=require("colord"),v=require("nativewind"),K=require("@react-navigation/native");function te({themeTokens:e,themeColors:t}){let{colorScheme:r,setColorScheme:o}=(0,v.useColorScheme)(),n=r==="light"?"light":"dark",{formattedColors:c,globalStyle:s,navTheme:f}=L.default.useMemo(()=>{let a={light:Y(t.light),dark:Y(t.dark)},i={light:ee("light",e,t),dark:ee("dark",e,t)},l={light:Z(K.DefaultTheme,a.light),dark:Z(K.DarkTheme,a.dark)};return{formattedColors:a,globalStyle:i,navTheme:l}},[t,e]);return L.default.useMemo(()=>({theme:{...e,colors:c[n]},navTheme:f[n],globalStyle:s[n],setColorScheme:o}),[c,s,f,n,o,e])}function ye(e){let t=e.includes(" ")&&!e.startsWith("hsl")?`hsl(${e})`:e;return(0,N.colord)(t).toHex()}function Y(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,ye(r)]))}function Z(e,t){return{...e,colors:{background:t.background,border:t.border,card:t.card,notification:t.destructive,primary:t.primary,text:t.foreground}}}function ge(e){let{h:t,s:r,l:o}=(0,N.colord)(e).toHsl();return`${t} ${r}% ${o}%`}function ee(e,t,r){return(0,v.vars)(Object.fromEntries([...Object.entries(t).map(([o,n])=>[`--${o}`,n]),...Object.entries(r[e]).map(([o,n])=>[`--${o}`,ge(n)])]))}
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import l,{useState as m}from"react";import{View as f,Text as y,StyleSheet as g}from"react-native";function d({style:t,children:o}){let[r,e]=m(0);return l.createElement(f,{style:t},l.createElement(y,{style:p.text,onPress:()=>{e(i=>i+1)}},"Box1 ",r),o)}var p=g.create({text:{fontSize:20,padding:15,borderRadius:10,color:"#ffffff",backgroundColor:"#0a234a"}});import{useEffect as h,useState as L}from"react";import*as c from"expo-screen-orientation";function x(){let[t,o]=L({orientation:void 0,orientationLock:void 0});return h(()=>{Promise.all([c.getOrientationAsync(),c.getOrientationLockAsync()]).then(([e,i])=>{o({orientation:e,orientationLock:i})});let r=c.addOrientationChangeListener(e=>{o({orientation:e.orientationInfo.orientation,orientationLock:e.orientationLock})});return()=>r.remove()},[]),t}import{useState as K}from"react";import{createMMKV as O,useMMKVListener as k}from"react-native-mmkv";function R({defaults:t,storage:o=O()}){let r=n=>{try{let a=o.getString(String(n));return a!==void 0?JSON.parse(a):t[n]}catch(a){return console.warn(a),t[n]}};return{useLocalStorage:n=>{let[a,s]=K(()=>r(n));return k(u=>{String(n)===u&&s(r(n))},o),a},setLocalStorage:(n,a)=>{try{let s=JSON.stringify(a);o.set(String(n),s)}catch(s){console.warn(s)}},getLocalStorage:n=>r(n),removeLocalStorage:n=>{try{o.remove(String(n))}catch(a){console.warn(a)}},clearAllLocalStorage:()=>{try{o.clearAll()}catch(n){console.warn(n)}},storage:o}}import v from"react";import{useNavigationContainerRef as V}from"expo-router";import w from"lodash/isEmpty";function C(){let t=V();v.useEffect(()=>{if(__DEV__)return t.addListener("state",()=>{let r=t.getState(),e=S(r);e&&(w(e.params)?console.log(`ROUTE CHANGED : ${e.name}`):console.log(`ROUTE CHANGED : ${e.name}`,e.params))})},[t])}function S(t){var o;if(!t)return null;if(t.routes&&t.routes.length>0){let r=(o=t.index)!=null?o:0,e=t.routes[r];if(!e)return null;if(e.state){let i=S(e.state);if(i)return i}return{name:e.name,params:e.params}}return null}export{d as Box1,R as createLocalStorage,C as useLogRouteChange,x as useOrientation};
1
+ import x,{useState as H}from"react";import{View as F,Text as $,StyleSheet as j}from"react-native";function D({style:e,children:t}){let[r,o]=H(0);return x.createElement(F,{style:e},x.createElement($,{style:I.text,onPress:()=>{o(n=>n+1)}},"Box1 ",r),t)}var I=j.create({text:{fontSize:20,padding:15,borderRadius:10,color:"#ffffff",backgroundColor:"#0a234a"}});import{useEffect as G,useState as _}from"react";import*as m from"expo-screen-orientation";function J(){let[e,t]=_({orientation:void 0,orientationLock:void 0});return G(()=>{Promise.all([m.getOrientationAsync(),m.getOrientationLockAsync()]).then(([o,n])=>{t({orientation:o,orientationLock:n})});let r=m.addOrientationChangeListener(o=>{t({orientation:o.orientationInfo.orientation,orientationLock:o.orientationLock})});return()=>r.remove()},[]),e}import U from"react";import{Platform as z,useColorScheme as W}from"react-native";import*as d from"expo-navigation-bar";function q(e){let t=W();U.useEffect(()=>{if(z.OS!=="android")return;d.setStyle(t==="dark"?"dark":"light");let r=t==="dark"?e==null?void 0:e.dark:e==null?void 0:e.light;if(!r)return;(async()=>{let n=[];r.backgroundColor&&(d.setBackgroundColorAsync(r.backgroundColor),n.push(d.setBackgroundColorAsync(r.backgroundColor))),r.borderColor&&n.push(d.setBorderColorAsync(r.borderColor)),n.length&&await Promise.all(n)})()},[t,e==null?void 0:e.dark,e==null?void 0:e.light])}import{useState as Q}from"react";import{createMMKV as X,useMMKVListener as Y}from"react-native-mmkv";function Z({defaults:e,storage:t=X()}){let r=a=>{try{let i=t.getString(String(a));return i!==void 0?JSON.parse(i):e[a]}catch(i){return console.warn(i),e[a]}};return{useLocalStorage:a=>{let[i,l]=Q(()=>r(a));return Y(S=>{String(a)===S&&l(r(a))},t),i},setLocalStorage:(a,i)=>{try{let l=JSON.stringify(i);t.set(String(a),l)}catch(l){console.warn(l)}},getLocalStorage:a=>r(a),removeLocalStorage:a=>{try{t.remove(String(a))}catch(i){console.warn(i)}},clearAllLocalStorage:()=>{try{t.clearAll()}catch(a){console.warn(a)}},storage:t}}import ee from"react";import{useNavigationContainerRef as te}from"expo-router";import oe from"lodash/isEmpty";function re(){let e=te();ee.useEffect(()=>{if(__DEV__)return e.addListener("state",()=>{let r=e.getState(),o=C(r);o&&(oe(o.params)?console.log(`ROUTE CHANGED : ${o.name}`):console.log(`ROUTE CHANGED : ${o.name}`,o.params))})},[e])}function C(e){var t;if(!e)return null;if(e.routes&&e.routes.length>0){let r=(t=e.index)!=null?t:0,o=e.routes[r];if(!o)return null;if(o.state){let n=C(o.state);if(n)return n}return{name:o.name,params:o.params}}return null}import u from"react";import{StyleSheet as v,View as T}from"react-native";import{cssInterop as ae}from"nativewind";import{SafeAreaView as ie}from"react-native-safe-area-context";import{KeyboardAwareScrollView as se}from"react-native-keyboard-controller";import ne,{useMemo as f}from"react";import{StyleSheet as h}from"react-native";import{useHeaderHeight as b}from"@react-navigation/elements";function y(e){return f(()=>e?typeof e=="function"?ne.createElement(e,null):e:null,[e])}function V(e,t){let r=b();return f(()=>{let o=h.flatten(e),n=o==null?void 0:o.padding,c=o==null?void 0:o.paddingTop,s=typeof c=="number"?c:typeof n=="number"?n:0;return t&&(s+=r),[R.flex,e,{paddingTop:s}]},[r,t,e])}function w(e,t){let r=b();return f(()=>{let o=h.flatten(e),n=o==null?void 0:o.padding,c=o==null?void 0:o.paddingTop,s=typeof c=="number"?c:typeof n=="number"?n:0;return t&&(s+=r),[R.scrollContentStyle,e,{paddingTop:s}]},[e,r,t])}var R=h.create({flex:{flex:1},scrollContentStyle:{flexGrow:1}});var ce=u.memo(function({scroll:t=!1,edges:r=[],headerTransparent:o=!1,scrollViewProps:n,scrollRef:c,style:s={},contentContainerStyle:p={},HeaderComponent:a,FooterComponent:i,BackgroundComponent:l,children:S}){let A=V(s,o),B=w(p,o),E=y(a),M=y(i),k=y(l);return u.createElement(T,{style:g.flex},k&&u.createElement(T,{style:g.background},k),u.createElement(ie,{edges:r,style:g.flex},E,t&&u.createElement(se,{ref:c,enabled:!0,scrollEnabled:!0,style:[g.flex,s],contentContainerStyle:B,bottomOffset:40,disableScrollOnKeyboardHide:!0,keyboardShouldPersistTaps:"handled",showsVerticalScrollIndicator:!1,...n},S),!t&&u.createElement(T,{style:[{overflow:"hidden"},A]},S),M))}),g=v.create({flex:{flex:1},background:{alignItems:"stretch",pointerEvents:"none",...v.absoluteFill}}),le=ae(ce,{className:"style",contentContainerClassName:"contentContainerStyle"});import K from"react";import{colord as O}from"colord";import{useColorScheme as de,vars as me}from"nativewind";import{DarkTheme as ue,DefaultTheme as pe}from"@react-navigation/native";function Se({themeTokens:e,themeColors:t}){let{colorScheme:r,setColorScheme:o}=de(),n=r==="light"?"light":"dark",{formattedColors:c,globalStyle:s,navTheme:p}=K.useMemo(()=>{let a={light:P(t.light),dark:P(t.dark)},i={light:N("light",e,t),dark:N("dark",e,t)},l={light:L(pe,a.light),dark:L(ue,a.dark)};return{formattedColors:a,globalStyle:i,navTheme:l}},[t,e]);return K.useMemo(()=>({theme:{...e,colors:c[n]},navTheme:p[n],globalStyle:s[n],setColorScheme:o}),[c,s,p,n,o,e])}function ye(e){let t=e.includes(" ")&&!e.startsWith("hsl")?`hsl(${e})`:e;return O(t).toHex()}function P(e){return Object.fromEntries(Object.entries(e).map(([t,r])=>[t,ye(r)]))}function L(e,t){return{...e,colors:{background:t.background,border:t.border,card:t.card,notification:t.destructive,primary:t.primary,text:t.foreground}}}function ge(e){let{h:t,s:r,l:o}=O(e).toHsl();return`${t} ${r}% ${o}%`}function N(e,t,r){return me(Object.fromEntries([...Object.entries(t).map(([o,n])=>[`--${o}`,n]),...Object.entries(r[e]).map(([o,n])=>[`--${o}`,ge(n)])]))}export{D as Box1,le as ScreenContent,Z as createLocalStorage,q as useAndroidNavigationBar,re as useLogRouteChange,J as useOrientation,Se as useThemeNativewind4};
@@ -1,4 +1,7 @@
1
1
  export { Box1 } from './components/Box1';
2
2
  export { useOrientation } from './utils/orientation';
3
+ export { useAndroidNavigationBar } from './utils/android-navbar';
3
4
  export { createLocalStorage } from './storage/local-storage';
4
- export { useLogRouteChange } from './navigation/utils';
5
+ export { useLogRouteChange } from './navigation/log-route';
6
+ export { ScreenContent, type ScreenContentProps, } from './navigation/screen-content/ScreenContent';
7
+ export { useThemeNativewind4 } from './nativewind/useTheme';
@@ -0,0 +1,60 @@
1
+ import { vars } from 'nativewind';
2
+ import { type Theme } from '@react-navigation/native';
3
+ /**
4
+ * Add theming support, by using Nativewind 4.
5
+ *
6
+ * ## Add theming to project
7
+ *
8
+ * Add to root component.
9
+ *
10
+ * ```
11
+ * import { ThemeProvider } from '@react-navigation/native';
12
+ * import { useThemeNativewind4 } from '@mbrain/epic-react-native-lib';
13
+ *
14
+ * const { navTheme, globalStyle } = useThemeNativewind4({
15
+ * themeColors,
16
+ * themeTokens,
17
+ * });
18
+ *
19
+ * <ThemeProvider value={navTheme}>
20
+ * <View className="flex-1" style={globalStyle}>
21
+ * {children}
22
+ * </View>
23
+ * </ThemeProvider>
24
+ * ```
25
+ *
26
+ * ## Use theme from anywhere
27
+ *
28
+ * ```
29
+ * const { theme } = useThemeNativewind4({ themeTokens, themeColors });
30
+ * const bgColor = colord(theme.colors['card']).alpha(0.6).toHex();
31
+ * ```
32
+ *
33
+ * ## Set Color Scheme
34
+ *
35
+ * ```
36
+ * setColorScheme('system');
37
+ * setColorScheme('light');
38
+ * setColorScheme('dark');
39
+ * ```
40
+ */
41
+ export declare function useThemeNativewind4<TTokens extends ThemeTokens, TVariant extends Record<string, string> = Record<string, string>>({ themeTokens, themeColors, }: {
42
+ themeTokens: TTokens;
43
+ themeColors: ThemeColors<TVariant>;
44
+ }): {
45
+ theme: ActiveTheme<TTokens, TVariant>;
46
+ navTheme: Theme;
47
+ globalStyle: ReturnType<typeof vars>;
48
+ setColorScheme: (value: 'light' | 'dark' | 'system') => void;
49
+ };
50
+ export type ThemeTokens = Record<string, string | number>;
51
+ export type ThemeColors<TVariant extends Record<string, string> = Record<string, string>> = {
52
+ light: TVariant;
53
+ dark: TVariant;
54
+ };
55
+ type ActiveTheme<TTokens extends ThemeTokens, TVariant extends Record<string, string>> = TTokens & {
56
+ colors: {
57
+ [K in keyof TVariant]: string;
58
+ };
59
+ };
60
+ export {};
@@ -0,0 +1,137 @@
1
+ import React from 'react';
2
+ import { StyleProp, ViewStyle } from 'react-native';
3
+ import { Edges } from 'react-native-safe-area-context';
4
+ import { KeyboardAwareScrollViewProps, KeyboardAwareScrollViewRef } from 'react-native-keyboard-controller';
5
+ type BaseScreenContentProps = {
6
+ /**
7
+ * Enable keyboard aware scrolling with [KeyboardAwareScrollView](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-aware-scroll-view).
8
+ *
9
+ * ## Requirement
10
+ *
11
+ * Add [KeyboardProvider](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/installation#adding-provider) as root app component.
12
+ *
13
+ * @default false
14
+ */
15
+ scroll?: boolean;
16
+ /**
17
+ * Safe area edges.
18
+ */
19
+ edges?: Edges;
20
+ /**
21
+ * Set to true when screen option headerTransparent is true.
22
+ *
23
+ * @default false
24
+ */
25
+ headerTransparent?: boolean;
26
+ /**
27
+ * A ref that will be attached to the underlying KeyboardAwareScrollView.
28
+ *
29
+ * Only used when scroll = true.
30
+ *
31
+ * ## Usage
32
+ *
33
+ * ```
34
+ * const scrollRef = useRef<KeyboardAwareScrollViewRef>(null);
35
+ * <ScreenContent scrollRef={scrollRef}>
36
+ * ```
37
+ */
38
+ scrollRef?: React.Ref<KeyboardAwareScrollViewRef>;
39
+ /**
40
+ * Set [KeyboardAwareScrollView](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/api/components/keyboard-aware-scroll-view) props. Only used when scroll = true.
41
+ *
42
+ * ## Usage
43
+ *
44
+ * ```
45
+ * scrollViewProps={{
46
+ * // The distance between the keyboard and the caret inside a focused TextInput when the keyboard is shown
47
+ * bottomOffset: 40,
48
+ * }}
49
+ * ```
50
+ */
51
+ scrollViewProps?: KeyboardAwareScrollViewProps;
52
+ /**
53
+ * Style applied to the container View.
54
+ */
55
+ style?: StyleProp<ViewStyle>;
56
+ /**
57
+ * Style applied to KeyboardAwareScrollView contentContainerStyle. Only used when scroll = true.
58
+ */
59
+ contentContainerStyle?: StyleProp<ViewStyle>;
60
+ /**
61
+ * Optional header component.
62
+ */
63
+ HeaderComponent?: React.FC | React.ReactNode;
64
+ /**
65
+ * Optional footer component.
66
+ *
67
+ * ## Usage
68
+ *
69
+ * Keyboard toolbar is always visible.
70
+ *
71
+ * ```typescript
72
+ * function FooterComponent({ onSubmit }: { onSubmit?: (text: string) => void }) {
73
+ * const [message, setMessage] = useState('');
74
+ *
75
+ * return (
76
+ * <KeyboardStickyView className="bg-background px-5 pb-5 pt-3">
77
+ * <Input
78
+ * placeholder="Type a message"
79
+ * returnKeyType="send"
80
+ * value={message}
81
+ * autoCorrect={false}
82
+ * autoCapitalize="none"
83
+ * onChangeText={(text) => {
84
+ * setMessage(text);
85
+ * }}
86
+ * onSubmitEditing={({ nativeEvent: { text } }) => {
87
+ * onSubmit?.(text);
88
+ * setMessage('');
89
+ * }}
90
+ * />
91
+ * </KeyboardStickyView>
92
+ * );
93
+ * }
94
+ * ```
95
+ */
96
+ FooterComponent?: React.FC | React.ReactNode;
97
+ /**
98
+ * Optional background component.
99
+ *
100
+ * ## Usage
101
+ *
102
+ * ```typescript
103
+ * function BackgroundComponent() {
104
+ * return (
105
+ * <View style={{ flex:1, backgroundColor: 'green' }} />
106
+ * );
107
+ * }
108
+ * ```
109
+ */
110
+ BackgroundComponent?: React.FC | React.ReactNode;
111
+ children?: React.ReactNode;
112
+ };
113
+ /**
114
+ * A comprehensive screen component that handles safe areas, scrolling and keyboard handling.
115
+ *
116
+ * ## Usage
117
+ *
118
+ * ```
119
+ * <ScreenContent
120
+ * scroll={true}
121
+ * edges={['bottom']}
122
+ * headerTransparent={false}
123
+ * scrollViewProps={{ bottomOffset: 40 }}
124
+ * contentContainerClassName="p-5 gap-3"
125
+ * >
126
+ * ```
127
+ *
128
+ * ## Requirement
129
+ *
130
+ * Add [KeyboardProvider](https://kirillzyusko.github.io/react-native-keyboard-controller/docs/installation#adding-provider) as root app component.
131
+ */
132
+ export declare const ScreenContent: React.ComponentType<BaseScreenContentProps & {
133
+ readonly className?: string | undefined;
134
+ readonly contentContainerClassName?: string | undefined;
135
+ }>;
136
+ export type ScreenContentProps = React.ComponentProps<typeof ScreenContent>;
137
+ export {};
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import { StyleProp, ViewStyle } from 'react-native';
3
+ export declare function useComponentNode(Component?: React.FC | React.ReactNode): React.ReactNode;
4
+ export declare function useFinalStyle(style: StyleProp<ViewStyle>, headerTransparent: boolean): StyleProp<ViewStyle>;
5
+ export declare function useFinalContentContainerStyle(contentContainerStyle: StyleProp<ViewStyle>, headerTransparent: boolean): StyleProp<ViewStyle>;
@@ -0,0 +1,23 @@
1
+ type NavigationBarThemeConfig = {
2
+ light?: {
3
+ borderColor?: string;
4
+ backgroundColor?: string;
5
+ };
6
+ dark?: {
7
+ borderColor?: string;
8
+ backgroundColor?: string;
9
+ };
10
+ };
11
+ /**
12
+ * Makes Android navigation bar follow current color schema (light, dark) with optional color overrides.
13
+ *
14
+ * ## Usage
15
+ *
16
+ * Add this hook to root layout.
17
+ *
18
+ * ```
19
+ * useAndroidNavigationBar();
20
+ * ```
21
+ */
22
+ export declare function useAndroidNavigationBar(config?: NavigationBarThemeConfig): void;
23
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mbrain/epic-react-native-lib",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "A set of helpful, battle-tested utilities that simplify common React Native workflows and speed up app development",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -34,10 +34,17 @@
34
34
  }
35
35
  },
36
36
  "dependencies": {
37
+ "@react-navigation/elements": "^2.9.1",
38
+ "@react-navigation/native": "^7.1.25",
39
+ "colord": "^2.9.3",
40
+ "expo-navigation-bar": "^5.0.10",
37
41
  "expo-router": "^6.0.17",
38
42
  "expo-screen-orientation": "^9.0.0",
39
43
  "lodash": "^4.17.21",
40
- "react-native-mmkv": "^4.0.1"
44
+ "nativewind": "^4.2.1",
45
+ "react-native-keyboard-controller": "^1",
46
+ "react-native-mmkv": "^4.0.1",
47
+ "react-native-safe-area-context": "^5.6.2"
41
48
  },
42
49
  "peerDependencies": {
43
50
  "react": ">=18.0.0",