kitcheningredients
v12.0.40
Published
A helper for the KitchenBase
Downloads
342
Readme
About
Helper for a base app template with a Directus Backend based on NativeBase. Written for React Web & React Native. Designed for an expo app.
- Login System to Directus
- React & React Native (expo)
- Based on NativeBase
- Synchronised States
- Synchronised Storage
- Easy Routing
- Lottie Files
Installation
npm install kitcheningredients
Usage
import { registerRootComponent } from 'expo';
import {App, ConfigHolder} from 'kitcheningredients'
import {MyDirectusStorage} from "kitcheningredients/lib/module/ignoreCoverage/KitchenHelper/storage/MyDirectusStorage";
import Project from "./src/project/Project";
import nativebaseConfig from "./nativebase.config";
import styleConfig from "./styleConfig.json";
import config from "./config.json";
import currentpackageJson from "./package.json";
import currentpackageJsonLock from "./package-lock.json";
import thirdpartyLicense from "./thirdpartyLicense.json"
import AppConfig from "./app.config"
ConfigHolder.instance.storage = new MyDirectusStorage();
ConfigHolder.plugin = new Project()
ConfigHolder.nativebaseConfig = nativebaseConfig
ConfigHolder.styleConfig = styleConfig
ConfigHolder.config = config
ConfigHolder.currentpackageJson = currentpackageJson
ConfigHolder.currentpackageJsonLock = currentpackageJsonLock
ConfigHolder.thirdpartyLicense = thirdpartyLicense
ConfigHolder.AppConfig = AppConfig
registerRootComponent(App);
import {ServerAPI} from "kitcheningredients";
export const TestDownload = (props) => {
async function download(){
let directus = ServerAPI.getClient();
const articles = await directus.items('articles').readByQuery({});
}
}
To get the logged in user and corresponding role you can use:
import {ConfigHolder} from "kitcheningredients";
let roleInstance = ConfigHolder.instance.getRole();
let userInstance = ConfigHolder.instance.getUser();
import {Example} from "./screens/example/Example";
import {BaseTemplate, PluginInterface, Menu, MenuItem} from "kitcheningredients";
export default class Project implements PluginInterface {
//...
registerRoutes() {
//Register your screen with the BaseTemplate or any other you like
Menu.registerRoute(Example, BaseTemplate, "Example", "example");
let myMenu = new MenuItem("ExampleMenu", "ExampleMenu", null, null, null, null, true);
Menu.registerCommonMenu(myMenu);
myMenu.addChildMenuItems(new MenuItem("ExampleItem", "ExampleItem", Example));
}
}
Role specific menus can be also registered:
import {MenuItem} from "kitcheningredients"
...
let menu = new MenuItem("ExampleItem", "ExampleItem", Example)
Menu.registerCommonMenu(menu); //Menu everyone can see
Menu.registerUnauthenticatedMenu(menu) //Menu unauthenticated users can see
Menu.registerAuthenticatedMenu(menu); //Menu authenticated users can see
Menu.registerMenuForRoleId("8cse873gbsbefu...", menu); //Menu only user with role id can see
//Attention! Multiple roles can have the same name
Menu.registerUnsafeMenuForRoleByName("Moderator", menu); //Menu only user with role which name is can see
let menu = new MenuItem(
key, // string: define a unique string for the menu item
label, //string: The displayed label
destination, //[default null] FunctionComponent: which was registered
items=null, //[default null] sub menu list
command=null, //[default null] function: will be called on selection
content=null, //[default null] JSX.Element: If no sub menus given, content will be shown
expanded=false, //[default false] boolean: if sub menus will be shown directly
customIcon //[can be null] string or function (string: MaterialCommunity Icon name) (function: (menu, hasChildren, expanded, props.level))
);
During the registering of your screens/routes you can add a template. Typicly you will use the BaseTemplate
.
export default class Project implements PluginInterface {
registerRoutes() {
Menu.registerRoute(Example, <TEMPLATE>, "Example", "example");
}
}
BaseTemplate
: IncludesBaseNoPaddingTemplate
and adds aBasePadding
. Includes KeyboardAvoidingView which works inside Scrollviews.- Usecase: You want to show text or a standard component
BasePadding
: Not a template but adds the base padding
BaseNoPaddingTemplate
: IncludesBaseNoPaddingTemplate
and a Scrollview with breakpoint layout for different screen sizes. Includes KeyboardAvoidingView which works inside Scrollviews.- Usecase: You want to scroll and use your own padding added but dont want to rerender for every screen change
BaseNoScrollTemplate
: Full width and height with basic title and drawer button without scrolling. Includes KeyboardAvoidingView which works inside Scrollviews.- Usecase: You want to implement a different scroll direction but want the drawer and title
EmptyTemplate
: Nothing but the props:height
andwidth
to all children- Usecase: You want to show a fullscreen map and dont want the drawer or title
Remember you can use Route-Templates
as your basic "Layout" or template for you content.
If you want to get informations about the Layout of your screen you can use the following informations.
import {Layout} from "kitcheningredients"
export const MyFunctionComponent = (props) => {
//boolean: true if using a small device
let isSmallDevice = Layout.usesSmallDevice(); //triggers rerendering on change
//number|string get the witdh of the content (e. G. "100%" or 700, ...)
let contentWidth = Layout.useBaseTemplateContentWidth(); //triggers rerendering on change
//get a dict with the layout sizes for different screen sizes
let rawWidthValues = Layout.getRawWidthValues()
}
If you want variables depending on the screen size you can use useBreakpointValue
.
Get more informations at: https://docs.nativebase.io/3.4.x/use-breakpoint-value
Example from NativeBase, where you can get either a row or a column value depending on the screen size:
import {useBreakpointValue} from "native-base";
export const MyFunctionComponent = (props) => {
const flexDir = useBreakpointValue({
base: "column",
lg: "row"
});
}
import {NavigatorHelper} from "kitcheningredients";
import {Example} from "./screens/example/Example";
export const Tutorial = (props) => {
// on button press
function onPress(){
// navigate to registered component
NavigatorHelper.navigate(Example, newProps, resetHistory);
// or navigate to a route
NavigatorHelper.navigateToRouteName(routeName, newProps, resetHistory)
}
}
TODO: navigateWithoutParams
TODO: toggleDrawer TODO: openDrawer TODO: closeDrawer TODO: goBack TODO: getRouteParams TODO: navigateHome
Auth
Authentication is done by the template. If you want to get the directus client, please read Server-API
abouve.
In order to allow users self registration follow these steps:
- Directus => Settings => Roles & Permissions => Role
Public
allow to createDirectus_users
(expand at bottom) atleastemail
andpassword
- [Optional] Set desired default role (<YOUR_DEFAULT_ROLE_ID>): Directus => Settings => Roles & Permissions => Role
Public
=> createDirectus_users
=> Field Presets =>{"role": "<YOUR_DEFAULT_ROLE_ID>"}
- Enable in your frontend app the button (in the index.js / index.web.js)
ConfigHolder.authConfig.mail.visible = true; //has to be enabled
ConfigHolder.authConfig.mail.registerVisible = true;
Synched States
Sometimes there is a need to synchronize states between different screens. This can be done by using the following functions.
You will first need to register a state (see State Registration
below). Then you can use the synchronized states (see Sync State usage
).
First you have to register the state you want to synchronize. You have the following options:
- Permanent: Save the state in the local storage
- Temporal: Save the state in the session storage
In the Project.tsx file return the following classes you created:
...
getSynchedStateKeysClass(){
return SynchedStateKeys;
}
getStorageKeysClass(){
return StorageKeys;
}
...
An example of the above one class is shown below:
export class SynchedStateKeys {
static exampleSynchedText = "SynchedStorage.exampleSynchedText"
}
Congrats, you are now able to use synched states accross your app.
In the Synched state only strings will be saved. If that is the case you can use useSynchedState
otherwise you can use useSynchedJSONState
.
- useSynchedState
import {useSynchedState} from "kitcheningredients";
export const MyFunctionComponent = (props) => {
const [myState, setMyState] = useSynchedState(SynchedStateKeys.exampleSynchedText);
}
- useSynchedJSONState Beware that the state will be saved as JSON.stringify and therefore you cannot have circular references.
import {useSynchedJSONState} from "kitcheningredients";
export const MyFunctionComponent = (props) => {
const [myJSONState, setMyJSONState] = useSynchedState(SynchedStateKeys.exampleSynchedJSON);
}
Components
Default Icons
import {Icon} from "kitcheningredients";
return (<Icon name={"account"} />) //Default MaterialIcons
Color and size
import {Icon} from "kitcheningredients";
return (<Icon name={"account"} color={"#FF0000"} size={"sm"} />) //Default MaterialIcons
More Icons
import {Ionicons} from "@expo/vector-icons";
import {Icon} from "kitcheningredients";
return (<Icon name={"account"} as={Ionicons} />)
import {TextWithIcon} from "kitcheningredients";
return (<TextWithIcon icon={"account"} content={"String"} />)
If you want to display an image from directus, like a mealImage or a user uploaded picture.
import {DirectusImage} from "kitcheningredients";
let myImageId = "sfsf6sef..."; //an image id you received
return (<DirectusImage assetId={myImageId} onPress={() => {console.log("Yeah!")}} />)
- assetId: string;
- The string of the immage id
- alt?: string;
- an alternative information if the image cant be shown
- url?: string;
- optional you can provide an url of an image from a different host like google,...
- style?: any;
- Styling object
- showLoading?: boolean
- default: true (shows a loading skeleton)
- isPublic?: boolean
- if the image resource is accessable for the public without authentication
- onPress?: () => {}
- A function which will be called on press
TODO: CrossLottie
You can use the KitchenSkeleton to show loading content. It will occupy the used space. More information at: https://docs.nativebase.io/3.4.x/skeleton#page-title
import {KitchenSkeleton} from "kitcheningredients";
return (<KitchenSkeleton flex={1} />)
You can use the Scrollview wrapper to show a gradient on the bottom, which indicates more content.
import {ScrollViewWithGradient} from "kitcheningredients";
return (
<ScrollViewWithGradient>
<Text>{"Lorem Ipsum long text or content"}</Text>
</ScrollViewWithGradient>
);
- hideGradient?: boolean
- Shows or hides the gradient
If you want to show a actionsheet you can use the MyActionsheet. It pops up on top of the screen.
import {MyActionsheet} from "kitcheningredients";
const actionsheet = MyActionsheet.useActionsheet();
const params = {
title: "Test",
onAccept: () => {console.log("Accept")},
...
};
actionsheet.show(params);
- title: string
- acceptLabel?: string
- default: "Accept"
- cancelLabel?: string
- default: "Cancel"
- onAccept?: () => {}
- A function which will be called on accept
- onCancel?: () => {}
- A function which will be called on cancel
- renderCustomContent?: () => {}
- A function which will be called to render the custom content
TODO: ThemedMarkdown TODO: DirectusMarkdown TODO: DirectusSingletonMarkdown
TODO: MyThemedBox
TODO: CustomFloaters
Created with
Builder Bob: https://github.com/callstack/react-native-builder-bob
Contributors
The FireboltCasters