Updated documentation

This commit is contained in:
Alejandro Zalazar 2021-04-23 10:09:13 -03:00
parent bd688c4c28
commit 574f3ac21f
4 changed files with 384 additions and 274 deletions

177
Documentation/Component.md Normal file
View File

@ -0,0 +1,177 @@
# Component programming guide
Welcome to the Kuru component programming guide! This guide aims to help you gain a deeper understanding of how components work, how to build them and how to deal with things like data binding, image loading and layout.
**Table of contents**
- [Introduction](#introduction)
- [The basics](#the-basics)
- [Defining properties for component](#defining-properties-for-component)
- [Rendering a component](#rendering-a-component)
- [Rendering a component with child components](#rendering-a-component-with-child-components)
- [Registering a component to use](#registering-a-component-to-use)
## Introduction
Components are the visual building blocks used to construct a View using the Kuru library.
Each component instance has a 1:1 relationship with its view, and is responsible for rendering a visual representation of a SwiftUI component. A component can also (optionally) have child components nested within it.
## The basics
To start creating a component, create a new class and make it conform to `KComponentProtocol`.
Initially, the implementation will look something like this:
```swift
import SwiftUI
import Kuru
struct JsonTextComponentExample: KComponentProtocol {
func render(withChildrens: [AnyView]) -> AnyView {
}
}
```
## Defining properties for component
The components property that enables you to set custom keys & values that can be used by your feature & components. This is an essential part of the API as it provides an easy way to extend the models for new ideas & concepts.
Properties must conform to the `Codable` protocol.
```swift
import SwiftUI
import Kuru
struct JsonViewComponentExample: KComponentProtocol {
var backgroundColor: Color? // Color+Codable extension is available in Kuru library
var width: CGFloat?
var height: CGFloat?
func render(withChildrens: [AnyView]) -> AnyView {
}
}
```
## Rendering a component
When its time for a component or render a visual representation of a model. The component itself decides what parts of the supplied properties that it wants to use, and how to bind the data contained within the model to any visual building blocks that it uses.
So again a component implementation is very free-form, you just need to add the implementation in the render method.
```swift
import SwiftUI
import Kuru
struct JsonViewComponentExample: KComponentProtocol {
var backgroundColor: Color? // Color+Codable extension is available in Kuru library
var width: CGFloat?
var height: CGFloat?
func render(withChildrens: [AnyView]) -> AnyView {
var body: some View {
}
return body
.background(backgroundColor)
.toAnyView() // View+ToAnyView extension is available in Kuru library
}
}
```
## Rendering a component with child components
Rendering a component with nested child components is so easy, you only need to add the children components inside itself in the render method.
```swift
import SwiftUI
import Kuru
struct JsonViewComponentExample: KComponentProtocol {
var backgroundColor: Color? // Color+Codable extension is available in Kuru library
var width: CGFloat?
var height: CGFloat?
func render(withChildrens: [AnyView]) -> AnyView {
var body: some View {
getView(childrens: withChildrens)
}
return body
.background(backgroundColor)
.toAnyView()
}
func getView(childrens: [AnyView]) -> AnyView {
// Render childrens components inside
let content =
ForEach(0..<childrens.count) { index in
childrens[index]
}
return content.toAnyView() // View+ToAnyView extension is available in Kuru library
}
}
```
## Registering a component to use
It's the time to register a custom component in Kuru library for use this. Registering a component is really easy only you need is call registerComponent or registerComponents method and specified the tag do you want to respond for this component.
```swift
import SwiftUI
import Kuru
@main
struct MyDemoApplication: App {
init() {
// Register component JsonViewComponentExample for type "view" in json data.
Kuru.registerComponent(JsonViewComponentExample.self, for: "view")
// Or register multiple components at the same time
Kuru.registerComponents(["view" : JsonViewComponentExample.self ])
}
var body: some Scene {
WindowGroup {
MyFirstView()
}
}
}
```

97
Documentation/Function.md Normal file
View File

@ -0,0 +1,97 @@
# Function programming guide
Welcome to the Kuru function programming guide! This guide aims to help you gain a deeper understanding of how functions work, how to create them and how you can use them to easily extend the framework with additional functionality.
**Table of contents**
- [Introduction](#introduction)
- [Creating a function](#creating-a-function)
- [Adding support for function in an existing component](#adding-support-for-function-in-an-existing-component)
## Introduction
Kuru framework comes with built-in selection handling for components. The function API also makes it easy to send events back to your content operations from your components.
## Creating a function
Functions are very simple to implement, all you require is one method:
```swift
import SwiftUI
import Kuru
@main
struct MyDemoApplication: App {
init() {
Kuru.registerFunction(name: "sayHello", completion: { params in
// Params are [String : Any]
print("Hello \(params?["name"] ?? "" )")
})
}
var body: some Scene {
WindowGroup {
MyFirstView()
}
}
}
```
## Adding support for function in an existing component
To integrate your function into a component create a property `KFunctionDecoder` type.
**Example**
`JsonButtonExampleComponent.swift`
```swift
import SwiftUI
import Kuru
struct JsonButtonExampleComponent: KComponentProtocol {
var text: String
var action: KFunctionDecoder //KFunctionDecoder is a json function decoder
func render(withChildrens: [AnyView]) -> AnyView {
Button(text, action: {
//Call action
action()
}).toAnyView()
}
}
```
`server.json`
```json
{
"type" : "button",
"args" : {
"text" : "Press here",
"action" : {
"name" : "sayHello",
"parameters" : {
"name" : "Alejandro"
}
}
}
}
```

89
Documentation/JSON.md Normal file
View File

@ -0,0 +1,89 @@
# JSON Programming Guide
Welcome to the Kuru JSON programming guide! This guide aims to act as a reference to the default JSON schema provided by the framework, and also contain information on how to enable a custom JSON schema to be used with the framework.
**Table of contents**
- [Introduction](#introduction)
- [JSON schema](#json-schema)
- [JSON function schema](#json-function-schema)
## Introduction
Kuru library enables content for views to be defined through JSON. This can make it a lot faster to ship content changes, since content can be defined completely in a server-side system, without requiring a client release.
## JSON schema
Here is a reference for the JSON schema:
| **Key** | Type | Description |
| --------- | ------ | ------------------------------------------------------------ |
| type | String | Specific the type of register component to use to render. Example : "type" : "view" |
| args | [ ] | Dictionary of properties for the component. Example [ "backgroundColor" : "#fff"] |
| childrens | [ ] | Dictionary of components to render as nested children's |
**Example**
```json
{
"type" : "your-register-component-type",
"args" : {
// Component properties like this
"text" : "Hello!"
},
"childrens" : [
// Pass components to render inside
{
"type" : "your-register-component-type",
"args" : {
// Component properties like this
"text" : "I'm inside!"
}
}
]
}
```
## JSON function schema
Kuru library support execute registered functions from server. Here is a reference for the function schema:
| Key | Type | Description |
| ---------- | ------ | ------------------------------------------------------------ |
| name | String | Name of registering function to call |
| parameters | [ ] | Parameters that registered function needed to success execution |
**Example**
```json
{
"type" : "your-register-component-type",
"args" : {
"action" : {
"name" : "your-function-name",
"parameters" : {
"name" : "Alejandro",
"years" : 30
}
}
},
"childrens" : []
}
```

295
README.md
View File

@ -7,15 +7,19 @@
Kuru is the easy way to manipulating ui data from a server in SwiftUI.
------
Welcome to Kuru - a toolkit for building native, component-driven UIs on iOS. It is designed to enable teams of any size to quickly build, tweak and ship new UI features, in either new or existing apps. It also makes it easy to build backend-driven UIs.
## Documentation
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Json Format](#json-format)
- [Register component](#register-component)
- [Using functions](#using-functions)
- [Getting started](#getting-started)
@ -34,7 +38,7 @@ Kuru is the easy way to manipulating ui data from a server in SwiftUI.
Kuru is available through [CocoaPods](https://cocoapods.org). To install it, simply add the following line to your Podfile:
```ruby
pod 'Kuru'
pod 'Kuru', '~> 0.0.3'
```
@ -53,294 +57,37 @@ dependencies: [
## Usage
## Getting started
There are also a series of **programming guides** that each introduce you to different aspects of the framework.
- [Component programming guide](https://github.com/zalazara/Kuru/Documentation/Component.md)
- [Json programming guide](https://github.com/zalazara/Kuru/Documentation/JSON.md)
- [Function programming guide](https://github.com/zalazara/Kuru/Documentation/Function.md)
### Json Format
Kuru library works with the following json contract:
```json
{
"type" : "your-register-component-type",
"args" : {
// Component properties like this
"text" : "Hello!"
},
"childrens" : [
// Pass components to render inside
{
"type" : "your-register-component-type",
"args" : {
// Component properties like this
"text" : "I'm inside!"
}
}
]
}
```
### Register component
Registering a component is really easy. All we need a class that implements JsonComponentProtocol interface.
***JsonViewComponentExample.swift***
### Basic implementation
```swift
import SwiftUI
import Kuru
struct JsonViewComponentExample: JsonComponentProtocol {
var backgroundColor: Color? // Color+Codable extension is available in Kuru library
func render(withChildrens: [AnyView]) -> AnyView {
var body: some View {
getView(childrens: withChildrens)
}
return body
.background(backgroundColor)
.toAnyView()
}
func getView(childrens: [AnyView]) -> AnyView {
// Render childrens components inside
let content =
ForEach(0..<childrens.count) { index in
childrens[index]
}
if let background = backgroundColor {
return AnyView(ZStack(content: {
background.edgesIgnoringSafeArea(.all)
VStack(content: {
content
})
}))
}
return content.toAnyView() // View+ToAnyView extension is available in Kuru library
}
}
```
***JsonTextComponentExample.swift***
```swift
import SwiftUI
import Kuru
struct JsonTextComponentExample: JsonComponentProtocol {
var text: String
var backgroundColor: Color? // Color+Codable extension is available in Kuru library
func render(withChildrens: [AnyView]) -> AnyView {
return generateTextWithProperties()
.toAnyView() // View+ToAnyView extension is available in Kuru library
}
private func generateTextWithProperties() -> some View {
return Text(self.text)
.background(backgroundColor)
}
}
```
***MyDemoApplication.swift***
```swift
import SwiftUI
import Kuru
@main
struct MyDemoApplication: App {
init() {
// Register component JsonViewComponentExample for type "view" in json data.
Kuru.registerComponent(JsonViewComponentExample.self, for: "view")
// Or register multiple components at the same time
//Kuru.registerComponents(["view" : JsonViewComponentExample.self ])
}
var body: some Scene {
WindowGroup {
MyFirstKuruView()
}
}
}
```
### Render
***MyFirstKuruView.swift***
```swift
import SwiftUI
import Kuru
struct MyFirstKuruView: View {
@State var viewData = Data() // Load json here
struct ContentView: View {
var body: some View {
Kuru.render(fromData: viewData);
Kuru.render(fromData: jsonData)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
MyFirstKuruView()
ContentView()
}
}
```
***server.Json***
```json
{
"type" : "view",
"args" : {
/// Properties for component
},
"children": [
...
{
"type" : "text",
"args" : {
"text" : "Hello world!",
"backgroundColor" : "#f00" //Background color is 8 hexadecimal format (hex with alpha)
}
}
...
]
}
```
## Usings functions
Kuru library supports registering dynamic functions that can be called from json.
## Json contract for function
```json
"action" : {
"name" : "your-function-name",
"parameters" : {
"name" : "Alejandro",
"years" : 30
}
}
```
### Register function
This is an example for register a function
***MyDemoApplication.swift***
```swift
import SwiftUI
import Kuru
@main
struct MyDemoApplication: App {
init() {
Kuru.registerFunction(name: "sayHello", completion: { params in
// Params are [String : Any]
print("Hello \(params?["name"] ?? "" )")
})
}
var body: some Scene {
WindowGroup {
MyFirstKuruView()
}
}
}
```
### Add support for function in my component
***JsonButtonExampleComponent.swift***
```swift
import SwiftUI
import Kuru
struct JsonButtonExampleComponent: JsonComponentProtocol {
var text: String
var action: KFunctionDecoder //KFunctionDecoder is a json function decoder
func render(withChildrens: [AnyView]) -> AnyView {
Button(text, action: { action() }).toAnyView()
}
}
```
### Send function in my server json
```json
{
"type" : "button",
"args" : {
"text" : "Press here",
"action" : {
"name" : "sayHello",
"parameters" : {
"name" : "Alejandro"
}
}
}
}
```
## Author
🥷🇦🇷 Alejandro Zalazar, azalazar@outlook.com.ar