Skip to content

Commit

Permalink
Merge branch 'feature/docs'
Browse files Browse the repository at this point in the history
  • Loading branch information
michielvandergeest committed Mar 11, 2024
2 parents 9891ce4 + 4c7fc64 commit f433154
Show file tree
Hide file tree
Showing 26 changed files with 606 additions and 398 deletions.
21 changes: 0 additions & 21 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,3 @@ Firstly, it's short, memorable and just has a nice ring to it.

Finally it's a nerdy reference to the computer term "Bit Blits" commonly used in graphics processing, for rapidly moving a block of data into memory - quite similar to what Lightning is doing 🙂

## Table of contents

- [Getting started](getting_started.md)
- [Components](components.md)
- [Template syntax](template_syntax.md)
- [Component state](component_state.md)
- [Hooking into lifecycle events](lifecycle_events.md)
- [Props](props.md)
- [Handling user input](user_input.md)
- [Computed properties](computed_properties.md)
- [Watching for changes](watchers.md)
- [Styling and positioning Elements](element_attributes.md)
- [Displaying images](displaying_images.md)

<!---
- More complex logic in methods
- Transitions
- Implementing Custom components
- Handling Text
- Routing
-->
30 changes: 18 additions & 12 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
- [Getting started](getting_started.md)
- [Components](components.md)
- [Template syntax](template_syntax.md)
- [Component state](component_state.md)
- [Hooking into lifecycle events](lifecycle_events.md)
- [Props](props.md)
- [Handling user input](user_input.md)
- [Computed properties](computed_properties.md)
- [Watching for changes](watchers.md)
- [Styling and positioning Elements](element_attributes.md)
- [Displaying images](displaying_images.md)
- [Text-to-Speech / Announcer](text-to-speech-announcer.md)
- Getting started
- [Intro](/readme.md)
- [Getting started](/getting_started/getting_started.md)
- [File structure](/getting_started/file_structure.md)
- Essentials
- [Application root](/essentials/application_root.md)
- [Component basics](/essentials/components.md)
- [Template syntax](/essentials/template_syntax.md)
- [Supported element attributes](/essentials/element_attributes.md)
- [Displaying images](/essentials/displaying_images.md)
- Components
- [State](/components/component_state.md)
- [Props](/components/props.md)
- [Computed properties](/components/computed_properties.md)
- [Watchers](/components/watchers.md)
- [Hooking into lifecycle events](/components/lifecycle_events.md)
- [Handling user input](/components/user_input.md)
- [Methods](/components/methods.md)

61 changes: 0 additions & 61 deletions docs/component_state.md

This file was deleted.

93 changes: 93 additions & 0 deletions docs/components/component_state.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Blits - Lightning 3 App Development Framework

## Component State

In Blits, a component can be as simple as a template with fixed, hardcoded values. However, for dynamic behavior and logic, you'll often want to give your components an _internal state_.

Some key concepts to keep in mind regarding Component state:

- The component state is defined within the `state` key of the Component configuration object.
- The `state` is expected to be a `function` (a regular function, not an ES6 arrow function), that returns an object representing the component's state.
- While defined on the configuration object, each component `instance` maintains its own distinct internal state.
- The structure of the `state` object is flexible, allowing you to define state values according to your component's requirements. These values can range from `strings`, `booleans`, `arrays`, to even nested `objects`.
- While you have full flexibility in structuring your state, be cautious about _excessive nesting_, as it could have a negative effect on performance.


Example of defining a component state:

```js
export default Blits.Component('MyComponent', {
// ...
state() {
return {
active: false,
items: [],
style: {
positions: {
x: 100,
},
dimensions: {
h: 100,
},
},
color: 'tomato'
}
}
})
```

### Accessing State in Templates

As explained in the [template section](/essentials/template_syntax.md), you can refer to state variables in a template by prefixing the state variable name with a _dollar sign_ (e.g., `$alpha`). Think of the `$`-sign as a reference to the `this`-scope of the component.

For nested objects, you can use _dot notation_ (e.g., `$style.dimensions.w`).

### Accessing State in Component Code

In your component's code, you can reference state variables directly within the `this`-scope. For instance, a state variable named `color` can be accessed (and modified) by referencing `this.color`.

It's important to note that unlike in the template, you should _not_ use the dollar sign when accessing state variables within the component's code.

Also remember that there is no need to explicitely reference the `state`-key. Blits automatically maps all state variables directly on the `this`-scope, for easy access.

The example below gives a full example of defining and using a component's state:

```js
export default Blits.Component('MyComponent', {
template: `
<Element :show="$active">
<Element :x="$style.x" w="100" :h="$style.dimensions.h">
<Element w="20" :h="$style.dimensions.h / 2" :color="$color" />
</Element>
</Element>
`,
state() {
return {
active: false,
items: [],
style: {
positions: {
x: 100,
},
dimensions: {
h: 100,
},
},
color: 'tomato'
}
}
hooks: {
ready() {
this.active = true
this.$setInterval(() => {
this.style.positions.x += 10
})
}
},
input: {
right() {
this.color = '#c0ffee'
}
}
})
```
48 changes: 48 additions & 0 deletions docs/components/computed_properties.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Blits - Lightning 3 App Development Framework

## Computed properties

So far we've learned how to utilize a Component's [internal state](./component_state.md) and [props](./props.md) passed by a parent into a child component.

We've also seen how we can perform simple operations like `Math.max()` or `str.toUpperCase()` directly within an argument of a template on the Component's internal state or passed props .

However as these operations become more complex it's more clear and more maintainable to abstract these operations into what we call _computed properties_.

Computed properties are a powerful tool for enhancing the readability of your component code. By abstracting complex or frequently used calculations from your template into computed properties, you can make your code more concise and easier to understand.


### Defining computed properties

Within the `computed`-key of the Component configuration object, you can specify an object of `functions`. Each function name you define (`offset()` for example) becomes accessible as a _computed property_.

A computed property function should always _return_ a value.

In your template, you can reference these computed properties exactly the same as you would with _state_ variable and _props_, by prefixing them with a dollar sign (e.g., `$offset`).

In the rest of your app's code, you can access these computed properties (but not modify them!) using `this.offset`. Note that similar to Component state and props, you do not need to prefix with `computed` to access the computed property.


```js
export default Blits.Component('MyComponent', {
// ...
computed: {
offset() {
return this.index * 100
},
bgColor() {
return this.focused === true ? 'aqua' : '#ccc'
}
}
})
```

### Reactivity

Within a computed property, you can reference one or more state variables or props and _return_ a value based on calculations or logical operations.

Whenever the value of any of the referenced variables changes, the computed property will automatically recalculate.

If a computed property is referenced reactively in the template (i.e., the argument is prefixed with colons `:`), it will also trigger an automatic rerender of that portion of the template.

Computed properties should **not** have any _side effects_ (i.e. should not change the value of any state variable). Side effects can potentially lead your app into an endless loop if not handled carefully. If you want to execute certain logic upon state changes, you can consider to use a [watcher](./watchers.md) for this.

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

Blits components follow a defined flow of lifecycle events. You can integrate specific logic into these events by specifying them in the `hooks` key of the Component configuration object.

For each available lifecycle event, you can define a function with the same name as the event itself. This function will execute each time the event is triggered for your component's instance. It's essential to use a regular function instead of an arrow function if you intend to access the `this` scope of your component instance.
For each available lifecycle event, you can define a function with the same name as the event itself. This function will then execute each time the lifecycle event is triggered for your component's instance. It's essential to use a regular function instead of an arrow function if you intend to access the `this` scope of your component instance.

### Lifecycle Events

- **init()**: This event fires when the component is instantiated, just before it sends its render instructions to the Lightning renderer. At this point, the elements of your template won't be available yet.
The following lifecycle events are available in Blits components.

- **init()**: This event fires when the component is being instantiated, just before it sends its render instructions to the Lightning renderer. At this point, the elements of your template won't be available yet.

- **ready()**: The `ready` event fires when the component instance is fully initialized and rendered, indicating that it's ready for interaction.

Expand Down
15 changes: 15 additions & 0 deletions docs/components/methods.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Blits - Lightning 3 App Development Framework

## Methods

Within a Blits component you have quite some freedom where to put specific logic.

Template related logic can be either be placed directly in a _reactive / interpolated_ attribute or you can move it out to a _computed property_ if the logic is more complex.

Business logic for your App can be placed directly in a _watcher_, a _lifecycle hook_ or an _input handling_ function.

If you notice that you're duplicating logic in these different places, or if you just like to keep all your business logic nicely grouped together, you can move these business logic functions under the `methods` key of the _Component configuration object_.

You can reference your Component's methods in the template by using a `$`-sign (for example in the `@loaded`-attribute when your element has a `src` attribute).

In the javascript code of a Component you can reference methods directly on the `this`-scope (i.e. `this.getData()`). Similar as with `internal` state and `props`, there is no need to prefix with `methods`, for easy access.
58 changes: 58 additions & 0 deletions docs/components/props.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Blits - Lightning 3 App Development Framework

## Props

Components in Blits have their own [internal state](./component_state.md) and logic, and as such a Component is self-contained. However, as each component is part of a larger App scope, they may need to display different behaviors or appearances based on the rest of the app.

To achieve this, components can receive `props` from their parent component.

### Defining and passing props

In the Component configuration object, you can specify exactly which props a component accepts. These props are passed to the component via attributes in the parent component's template. Any attributes that are not explicitly defined as a prop will be ignored.

The `props` key in the Component configuration object should be an `Array`, where each item corresponds to a prop that the component can accept.

The simplest way to define props is to just list their names within the `props` array:

```js
{
props: ['x', 'color', 'index', 'alpha']
}
```

Once specified, you can refer to these props inside the template of your component using the `$` sign, similar to how you would reference variables defined within the component's [internal state](./component_state.md) (i.e. `<Element color="$color" />`).

You can als access a prop inside a component's code using `this.color` (without a dollar sign!). And similar to component `state` variables,
there is no need to specifically reference the `props`-key. Blits automatically maps all props directly on the `this`-scope, for easy access.

Since props are used to pass information from a parent to a child, it's important not to attempt to _modify_ props inside your child component. If changes based on the prop from the parent are needed, you should probably use the prop in a so called [computed property](./computed_properties.md).

### Advanced usage

For more advanced usage, you can define props using an array with an `object` for each prop, instead of just a string with the accepted name. Within each prop object, you can:

- Specify a _default value_ for the prop if it's omitted.
- _Validate_ the value of the prop based on certain criteria.
- Mark the prop as _required_.
- Apply a `cast` function to modify the value passed as a prop.

As you can see in the following example, you can mix and match the simple string notation with the advanced object notation within the same `props` array.


```js
export default Blits.Component('MyComponent', {
// ...
props: [
'color',
{
key: 'alpha',
default: 0.5,
required: true,
validate(v) {
return v <= 1 && v >= 0;
},
cast: Number
}
]
})
```
Loading

0 comments on commit f433154

Please sign in to comment.