UNPKG

rn-dynamic-ui-render

Version:
375 lines (307 loc) โ€ข 8.57 kB
# ๐Ÿงฉ rn-dynamic-ui-render A powerful, schema-driven UI rendering engine for React Native. Build customizable, market-specific UIs without writing static layouts. Ideal for white-labeled or modular applications. ## โœจ Features * **Schema-Based UI**: Define views using JSON instead of JSX for maximum flexibility. * **Dynamic Rendering**: Supports nested layouts, conditional visibility, dynamic styles, and list rendering. * **Theming Support**: Centralize colors, fonts, and design tokens for consistent styling. * **Internationalization**: Built-in support for translations via `react-i18next`. * **Extensible**: Inject custom logic, actions, helpers, and data context. * **Safe Evaluation**: Scoped expression evaluation with robust fallback handling. * **List Rendering**: Seamless integration with `FlatList` for complex, repeatable UIs. ## ๐Ÿ“ฆ Installation Install the package via npm or yarn: ```bash npm install rn-dynamic-ui-render # or yarn add rn-dynamic-ui-render ``` ### Peer Dependencies * `react-native` (>= 0.60) * `react-i18next` (optional, for translation support) Install peer dependencies: ```bash npm install react-native react-i18next ``` ## ๐Ÿš€ Getting Started 1. Install the package and peer dependencies as shown above. 2. Create a JSON schema defining your UI. 3. Pass the schema, theme, handlers, and components to `RNDynamicUIRender`. 4. Optionally, enable translations by setting `translate: true`. ## ๐Ÿ”ง Basic Usage ```jsx import React from "react"; import { View, Text, Button, FlatList } from "react-native"; import RNDynamicUIRender from "rn-dynamic-ui-render"; // Example schema const schema = [ { name: "View", props: { style: { padding: 16 } }, content: [ { name: "Text", props: { textContent: "welcome_title", // Key for translation style: { fontSize: "large", color: "primary", fontWeight: "bold", }, }, }, { name: "Button", props: { title: "Click Me", onPress: "handlePress", passData: true, }, }, ], }, ]; // Theme configuration const theme = { colors: { primary: "#0066ff", danger: "#cc0000", }, font: { large: 24, medium: 16, }, fontWeight: { bold: "700", regular: "400", }, }; // Handlers for logic and data const handlers = { handlePress: (item, index) => alert(`Pressed! Item: ${JSON.stringify(item)}, Index: ${index}`), user: { name: "John", age: 25, isLoggedIn: true }, }; export default function App() { return ( <RNDynamicUIRender data={schema} handlers={handlers} theme={theme} components={{ View, Text, Button, FlatList }} translate={true} // Enable translations /> ); } ``` > ๐Ÿ“ Note: For translations, configure `react-i18next` as per its documentation. The `textContent` prop (e.g., `welcome_title`) maps to a translation key. ## ๐Ÿงฉ Schema Format Each node in the schema is a JSON object with the following structure: ```ts { name: string; // Component name (e.g., 'Text', 'View') props?: object; // Props passed to the component content?: array; // Child nodes to render inside if?: string | boolean; // Conditional visibility (expression or boolean) visible?: string | boolean; // Alternative visibility control visibleExpression?: true; // Use expression-based visibility listHeaderComponent?: array; // FlatList header listFooterComponent?: array; // FlatList footer listEmptyComponent?: array; // FlatList empty state } ``` ### Example: ```json { "name": "Text", "props": { "textContent": "Welcome back!", "if": "{{ user.isLoggedIn }}" } } ``` ## ๐Ÿง  Expression Logic Expressions allow dynamic logic in schemas using JavaScript-like syntax, safely evaluated in a scoped context. ### Supported: * Variables: `user.name` * Ternary operators: `{{ user.age > 18 ? 'Adult' : 'Minor' }}` * List item access: `item.price` (inside FlatList) ### Examples: #### Visibility: ```json { "name": "Text", "props": { "textContent": "Welcome back!", "if": "{{ user.isLoggedIn }}" } } ``` #### Dynamic Styling: ```json { "name": "Text", "props": { "style": { "fontSize": { "expression": "{{ user.age > 18 ? 22 : 16 }}" } } } } ``` ## ๐Ÿ” FlatList Support ```json { "name": "FlatList", "props": { "data": "userList", "keyExtractor": "id" }, "content": [ { "name": "Text", "props": { "textContent": "item.name" } } ], "listHeaderComponent": [ { "name": "Text", "props": { "textContent": "User List" } } ], "listEmptyComponent": [ { "name": "Text", "props": { "textContent": "No users found" } } ] } ``` > โ„น๏ธ `keyExtractor` can be a string or function. `$item$` and `$index$` are auto-injected in list rows. ## ๐ŸŽจ Theming ```ts const theme = { colors: { primary: "#0066ff", text: "#333", }, font: { small: 14, large: 24, }, fontWeight: { regular: "400", bold: "700", }, }; ``` ### Use tokens in schemas: ```json { "name": "Text", "props": { "style": { "color": "primary", "fontSize": "large", "fontWeight": "bold" } } } ``` ## ๐Ÿง  Handlers & Actions ```jsx <RNDynamicUIRender handlers={{ user: { name: "Alex", isLoggedIn: true }, userList: [ { id: "1", name: "Alice" }, { id: "2", name: "Bob" }, ], handleClick: (item, index) => alert(`Clicked: ${item?.name}, Index: ${index}`), }} /> ``` > Props like `onPress` and `onChange` resolve to handler keys. Use `passData: true` to inject list item & index. ## โœ… Component Props | Prop | Type | Description | Default | | ------------ | ------- | ------------------------------------- | ------- | | `data` | array | JSON schema defining the UI | - | | `handlers` | object | Data and logic context | `{}` | | `components` | object | Custom component registry | `{}` | | `theme` | object | Design tokens for styling | `{}` | | `translate` | boolean | Enable translations via react-i18next | `false` | ## ๐Ÿงช TypeScript Support ```tsx import RNDynamicUIRender, { SchemaNode } from "rn-dynamic-ui-render"; const schema: SchemaNode[] = [ { name: "Text", props: { textContent: "Hello, TypeScript!" }, }, ]; <RNDynamicUIRender data={schema} translate={true} />; ``` Covers types for: * `RNDynamicUIRender` component * SchemaNode format * Handlers, theme, props ## ๐Ÿ“š Examples ### Conditional UI ```json [ { "name": "View", "content": [ { "name": "Text", "props": { "textContent": "{{ user.isLoggedIn ? 'Welcome back!' : 'Please log in' }}" } } ] } ] ``` ### Dynamic List ```json { "name": "FlatList", "props": { "data": "userList", "keyExtractor": "id" }, "content": [ { "name": "View", "props": { "style": { "padding": 8 } }, "content": [ { "name": "Text", "props": { "textContent": "item.name" } } ] } ] } ``` ## ๐Ÿค Contributing Contributions are welcome! Please follow these steps: 1. Fork the repository. 2. Create a feature branch: `git checkout -b feature/your-feature` 3. Commit your changes: `git commit -m 'Add feature'` 4. Push to the branch: `git push origin feature/your-feature` 5. Open a pull request. See `CONTRIBUTING.md` for details. ## ๐Ÿ“œ License This project is licensed under the MIT License. See the `LICENSE` file for details. ## โ“ FAQ **Q: Why are my translations not working?** **A:** Ensure `react-i18next` is configured and `translate: true` is set in `RNDynamicUIRender`. **Q: How do I debug schema errors?** **A:** Check the console for errors. Ensure `name` matches a registered component and expressions are valid. **Q: Can I use custom components?** **A:** Yes, pass them in the `components` prop, e.g., `{ MyComponent }`. ---