Updated documentation
This commit is contained in:
parent
bd688c4c28
commit
574f3ac21f
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -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
295
README.md
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue