@lightningjs/blits 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/boilerplate/js/default/src/index.js +2 -8
- package/docs/README.md +0 -21
- package/docs/_sidebar.md +25 -13
- package/docs/built-in/directives.md +44 -0
- package/docs/{component_state.md → components/component_state.md} +37 -5
- package/docs/components/computed_properties.md +48 -0
- package/docs/{lifecycle_events.md → components/lifecycle_events.md} +4 -2
- package/docs/components/methods.md +47 -0
- package/docs/components/props.md +58 -0
- package/docs/{user_input.md → components/user_input.md} +31 -26
- package/docs/components/utilities.md +4 -0
- package/docs/components/watchers.md +36 -0
- package/docs/essentials/application_root.md +21 -0
- package/docs/{components.md → essentials/components.md} +17 -5
- package/docs/{displaying_images.md → essentials/displaying_images.md} +7 -7
- package/docs/essentials/displaying_text.md +77 -0
- package/docs/{element_attributes.md → essentials/element_attributes.md} +17 -12
- package/docs/essentials/template_syntax.md +85 -0
- package/docs/getting_started/file_structure.md +61 -0
- package/docs/getting_started/getting_started.md +47 -0
- package/docs/{introduction.md → getting_started/intro.md} +2 -1
- package/docs/sidebar.json +70 -26
- package/docs/transitions_animations/transitions.md +132 -0
- package/package.json +2 -3
- package/src/component.js +12 -3
- package/src/element.js +3 -0
- package/src/fontLoader.js +20 -21
- package/src/launch.d.ts +5 -6
- package/src/launch.js +12 -2
- package/src/lib/codegenerator/generator.js +2 -2
- package/src/lib/colors/colors.js +50 -40
- package/src/lib/colors/colors.test.js +149 -49
- package/src/lib/colors/htmlColors.js +149 -149
- package/src/lib/hooks.js +7 -7
- package/src/lib/lifecycle.js +3 -2
- package/src/lib/setup/base.js +19 -11
- package/src/lib/setup/state.js +1 -1
- package/src/lib/symbols.js +2 -0
- package/src/lib/templateparser/parser.js +50 -12
- package/src/lib/templateparser/parser.test.js +378 -71
- package/src/router/router.js +6 -6
- package/vite/msdfGenerator.js +1 -1
- package/boilerplate/js/default/src/fontloader.js +0 -4
- package/docs/computed_properties.md +0 -18
- package/docs/getting_started.md +0 -40
- package/docs/props.md +0 -46
- package/docs/template_syntax.md +0 -65
- package/docs/watchers.md +0 -38
- /package/docs/{text-to-speech-announcer.md → plugins/text-to-speech-announcer.md} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
# v0.9.0
|
|
4
|
+
|
|
5
|
+
_18 mar 2024_
|
|
6
|
+
|
|
7
|
+
- Added symbol for `id` on component
|
|
8
|
+
- Fixed issue in for loop when `:key` is a number (and not a string)
|
|
9
|
+
- Added built-in `hasFocus` state variable, available on every Component
|
|
10
|
+
- Refactored font loading, removed the need for temporary `src/fontLoader.js` file
|
|
11
|
+
- Replaced using component name with unique identifier for registering and emitting hooks
|
|
12
|
+
|
|
13
|
+
# v0.8.1
|
|
14
|
+
|
|
15
|
+
_9 mar 2024_
|
|
16
|
+
|
|
17
|
+
- Added pre-processing of hardcoded colors used in the template
|
|
18
|
+
- Upgraded Lightning renderer to v0.7.5
|
|
19
|
+
- Removed explicit destroy of child nodes, as the renderer now takes care of this
|
|
20
|
+
- Re-added support for clipping
|
|
21
|
+
|
|
3
22
|
# v0.8.0
|
|
4
23
|
|
|
5
24
|
_1 mar 2024_
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import Blits from '@lightningjs/blits'
|
|
2
|
-
// @ts-ignore
|
|
3
|
-
import fontLoader from './fontloader.js?importChunkUrl'
|
|
4
|
-
|
|
5
2
|
import App from './App.js'
|
|
6
3
|
|
|
7
4
|
Blits.Launch(App, 'app', {
|
|
@@ -9,19 +6,16 @@ Blits.Launch(App, 'app', {
|
|
|
9
6
|
h: 1080,
|
|
10
7
|
multithreaded: false,
|
|
11
8
|
debugLevel: 1,
|
|
12
|
-
fontLoader: fontLoader,
|
|
13
9
|
fonts: [
|
|
14
10
|
{
|
|
15
11
|
family: 'lato',
|
|
16
12
|
type: 'msdf',
|
|
17
|
-
|
|
18
|
-
json: 'fonts/Lato-Regular.msdf.json',
|
|
13
|
+
file: 'fonts/Lato-Regular.ttf',
|
|
19
14
|
},
|
|
20
15
|
{
|
|
21
16
|
family: 'raleway',
|
|
22
17
|
type: 'msdf',
|
|
23
|
-
|
|
24
|
-
json: 'fonts/Raleway-ExtraBold.msdf.json',
|
|
18
|
+
file: 'fonts/Raleway-ExtraBold.ttf',
|
|
25
19
|
},
|
|
26
20
|
{
|
|
27
21
|
family: 'opensans',
|
package/docs/README.md
CHANGED
|
@@ -18,24 +18,3 @@ Firstly, it's short, memorable and just has a nice ring to it.
|
|
|
18
18
|
|
|
19
19
|
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 🙂
|
|
20
20
|
|
|
21
|
-
## Table of contents
|
|
22
|
-
|
|
23
|
-
- [Getting started](getting_started.md)
|
|
24
|
-
- [Components](components.md)
|
|
25
|
-
- [Template syntax](template_syntax.md)
|
|
26
|
-
- [Component state](component_state.md)
|
|
27
|
-
- [Hooking into lifecycle events](lifecycle_events.md)
|
|
28
|
-
- [Props](props.md)
|
|
29
|
-
- [Handling user input](user_input.md)
|
|
30
|
-
- [Computed properties](computed_properties.md)
|
|
31
|
-
- [Watching for changes](watchers.md)
|
|
32
|
-
- [Styling and positioning Elements](element_attributes.md)
|
|
33
|
-
- [Displaying images](displaying_images.md)
|
|
34
|
-
|
|
35
|
-
<!---
|
|
36
|
-
- More complex logic in methods
|
|
37
|
-
- Transitions
|
|
38
|
-
- Implementing Custom components
|
|
39
|
-
- Handling Text
|
|
40
|
-
- Routing
|
|
41
|
-
-->
|
package/docs/_sidebar.md
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
-
|
|
2
|
-
- [
|
|
3
|
-
- [
|
|
4
|
-
- [
|
|
5
|
-
-
|
|
6
|
-
- [
|
|
7
|
-
- [
|
|
8
|
-
- [
|
|
9
|
-
- [
|
|
10
|
-
- [
|
|
11
|
-
- [Displaying
|
|
12
|
-
-
|
|
13
|
-
|
|
1
|
+
- Getting started
|
|
2
|
+
- [Intro](/getting_started/intro.md)
|
|
3
|
+
- [Getting started](/getting_started/getting_started.md)
|
|
4
|
+
- [File structure](/getting_started/file_structure.md)
|
|
5
|
+
- Essentials
|
|
6
|
+
- [Application root](/essentials/application_root.md)
|
|
7
|
+
- [Component basics](/essentials/components.md)
|
|
8
|
+
- [Template syntax](/essentials/template_syntax.md)
|
|
9
|
+
- [Supported element attributes](/essentials/element_attributes.md)
|
|
10
|
+
- [Displaying images](/essentials/displaying_images.md)
|
|
11
|
+
- [Displaying text](/essentials/displaying_text.md)
|
|
12
|
+
- Components
|
|
13
|
+
- [State](/components/component_state.md)
|
|
14
|
+
- [Props](/components/props.md)
|
|
15
|
+
- [Computed properties](/components/computed_properties.md)
|
|
16
|
+
- [Watchers](/components/watchers.md)
|
|
17
|
+
- [Hooking into lifecycle events](/components/lifecycle_events.md)
|
|
18
|
+
- [Handling User input](/components/user_input.md)
|
|
19
|
+
- [Methods](/components/methods.md)
|
|
20
|
+
- Transitions and Animations
|
|
21
|
+
- [Transitions](/transitions_animations/transitions.md)
|
|
22
|
+
- Built-in components
|
|
23
|
+
- [Directives](/built-in/directives.md)
|
|
24
|
+
- Plugins
|
|
25
|
+
- [Text-to-Speech / Announcer](/plugins/text-to-speech-announcer.md)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Blits - Lightning 3 App Development Framework
|
|
2
|
+
|
|
3
|
+
## Directives
|
|
4
|
+
|
|
5
|
+
Blits comes with a few built-in attributes that tap into specific behaviour provided by the framework - also kn ows as _directives_. Most of them can be used in the template on both Elements and Components.
|
|
6
|
+
|
|
7
|
+
### Show-directive
|
|
8
|
+
|
|
9
|
+
The `show`-attribute allows you to conditionally show and hide Components and Elements.
|
|
10
|
+
|
|
11
|
+
When passed a _truthy_ value, such as `true` or `1`, the element will be made visible. And when passed a _falsy_ value (`false` or `0`) it will not be visible.
|
|
12
|
+
|
|
13
|
+
```xml
|
|
14
|
+
<Element>
|
|
15
|
+
<Element w="100" h="100" color="purple" :show="$active"></Element>
|
|
16
|
+
<Element w="100" h="100" y="200" color="purple" show="false"></Element>
|
|
17
|
+
</Element>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Is-directive
|
|
21
|
+
|
|
22
|
+
The `is` directive allows you to dynamically instantiate a Component based on a `state` variable or a passed `prop`.
|
|
23
|
+
|
|
24
|
+
It is very useful in combination with API driven Apps, where the type of Component to use, depends on what data is returned (i.e. a `Poster` or a `HeroImage`).
|
|
25
|
+
|
|
26
|
+
The `is`-component should always be used together with the built-in `Component`-tag.
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
export default Blits('DynamicComponents', {
|
|
30
|
+
template: `
|
|
31
|
+
<Element>
|
|
32
|
+
<Component is="$firstComponent" />
|
|
33
|
+
<Component is="$secondComponent" x="500" />
|
|
34
|
+
</Element>
|
|
35
|
+
`,
|
|
36
|
+
props: ['firstComponent', 'secondComponent'],
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
At the moment it's not possible to use the `is`-attribute as a _reactive_ attribute and have a component change type after instantiation.
|
|
41
|
+
|
|
42
|
+
<!-- ### If-directive
|
|
43
|
+
|
|
44
|
+
Todo -->
|
|
@@ -2,23 +2,55 @@
|
|
|
2
2
|
|
|
3
3
|
## Component State
|
|
4
4
|
|
|
5
|
-
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
|
|
5
|
+
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_.
|
|
6
6
|
|
|
7
7
|
Some key concepts to keep in mind regarding Component state:
|
|
8
8
|
|
|
9
|
-
- Each component _instance_ maintains its own distinct internal state.
|
|
10
9
|
- The component state is defined within the `state` key of the Component configuration object.
|
|
11
10
|
- 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.
|
|
11
|
+
- While defined on the configuration object, each component `instance` maintains its own distinct internal state.
|
|
12
12
|
- 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`.
|
|
13
|
-
- While flexibility in structuring your state
|
|
13
|
+
- While you have full flexibility in structuring your state, be cautious about _excessive nesting_, as it could have a negative effect on performance.
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Example of defining a component state:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
export default Blits.Component('MyComponent', {
|
|
20
|
+
// ...
|
|
21
|
+
state() {
|
|
22
|
+
return {
|
|
23
|
+
active: false,
|
|
24
|
+
items: [],
|
|
25
|
+
style: {
|
|
26
|
+
positions: {
|
|
27
|
+
x: 100,
|
|
28
|
+
},
|
|
29
|
+
dimensions: {
|
|
30
|
+
h: 100,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
color: 'tomato'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
```
|
|
14
38
|
|
|
15
39
|
### Accessing State in Templates
|
|
16
40
|
|
|
17
|
-
As explained in the [template section](
|
|
41
|
+
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.
|
|
42
|
+
|
|
43
|
+
For nested objects, you can use _dot notation_ (e.g., `$style.dimensions.w`).
|
|
18
44
|
|
|
19
45
|
### Accessing State in Component Code
|
|
20
46
|
|
|
21
|
-
In your component's code, you can reference state variables within the `this
|
|
47
|
+
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`.
|
|
48
|
+
|
|
49
|
+
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.
|
|
50
|
+
|
|
51
|
+
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.
|
|
52
|
+
|
|
53
|
+
The example below gives a full example of defining and using a component's state:
|
|
22
54
|
|
|
23
55
|
```js
|
|
24
56
|
export default Blits.Component('MyComponent', {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Blits - Lightning 3 App Development Framework
|
|
2
|
+
|
|
3
|
+
## Computed properties
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
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 .
|
|
8
|
+
|
|
9
|
+
However as these operations become more complex it's more clear and more maintainable to abstract these operations into what we call _computed properties_.
|
|
10
|
+
|
|
11
|
+
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.
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Defining computed properties
|
|
15
|
+
|
|
16
|
+
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_.
|
|
17
|
+
|
|
18
|
+
A computed property function should always _return_ a value.
|
|
19
|
+
|
|
20
|
+
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`).
|
|
21
|
+
|
|
22
|
+
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.
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
export default Blits.Component('MyComponent', {
|
|
27
|
+
// ...
|
|
28
|
+
computed: {
|
|
29
|
+
offset() {
|
|
30
|
+
return this.index * 100
|
|
31
|
+
},
|
|
32
|
+
bgColor() {
|
|
33
|
+
return this.focused === true ? 'aqua' : '#ccc'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Reactivity
|
|
40
|
+
|
|
41
|
+
Within a computed property, you can reference one or more state variables or props and _return_ a value based on calculations or logical operations.
|
|
42
|
+
|
|
43
|
+
Whenever the value of any of the referenced variables changes, the computed property will automatically recalculate.
|
|
44
|
+
|
|
45
|
+
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.
|
|
46
|
+
|
|
47
|
+
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.
|
|
48
|
+
|
|
@@ -4,11 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
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.
|
|
6
6
|
|
|
7
|
-
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.
|
|
7
|
+
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.
|
|
8
8
|
|
|
9
9
|
### Lifecycle Events
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The following lifecycle events are available in Blits components.
|
|
12
|
+
|
|
13
|
+
- **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.
|
|
12
14
|
|
|
13
15
|
- **ready()**: The `ready` event fires when the component instance is fully initialized and rendered, indicating that it's ready for interaction.
|
|
14
16
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Blits - Lightning 3 App Development Framework
|
|
2
|
+
|
|
3
|
+
## Methods
|
|
4
|
+
|
|
5
|
+
Within a Blits component you have quite some freedom where to put specific logic.
|
|
6
|
+
|
|
7
|
+
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.
|
|
8
|
+
|
|
9
|
+
Business logic for your App can be placed directly in a _watcher_, a _lifecycle hook_ or an _input handling_ function.
|
|
10
|
+
|
|
11
|
+
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_.
|
|
12
|
+
|
|
13
|
+
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).
|
|
14
|
+
|
|
15
|
+
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.
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
export default Blits('Carousel', {
|
|
19
|
+
template: `
|
|
20
|
+
<Element>
|
|
21
|
+
<!-- .... -->
|
|
22
|
+
</Element>
|
|
23
|
+
`,
|
|
24
|
+
state() {
|
|
25
|
+
return {
|
|
26
|
+
items: [],
|
|
27
|
+
page: 0
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
hooks: {
|
|
31
|
+
ready() {
|
|
32
|
+
this.fetchData()
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
input: {
|
|
36
|
+
down() {
|
|
37
|
+
this.page++
|
|
38
|
+
this.fetchData()
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
methods: {
|
|
42
|
+
async fetchData() {
|
|
43
|
+
this.items = await API.get(['movies', 'tvshows', 'documentaries'], this.page)
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
```
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Blits - Lightning 3 App Development Framework
|
|
2
|
+
|
|
3
|
+
## Props
|
|
4
|
+
|
|
5
|
+
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.
|
|
6
|
+
|
|
7
|
+
To achieve this, components can receive `props` from their parent component.
|
|
8
|
+
|
|
9
|
+
### Defining and passing props
|
|
10
|
+
|
|
11
|
+
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.
|
|
12
|
+
|
|
13
|
+
The `props` key in the Component configuration object should be an `Array`, where each item corresponds to a prop that the component can accept.
|
|
14
|
+
|
|
15
|
+
The simplest way to define props is to just list their names within the `props` array:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
{
|
|
19
|
+
props: ['x', 'color', 'index', 'alpha']
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
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" />`).
|
|
24
|
+
|
|
25
|
+
You can als access a prop inside a component's code using `this.color` (without a dollar sign!). And similar to component `state` variables,
|
|
26
|
+
there is no need to specifically reference the `props`-key. Blits automatically maps all props directly on the `this`-scope, for easy access.
|
|
27
|
+
|
|
28
|
+
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).
|
|
29
|
+
|
|
30
|
+
### Advanced usage
|
|
31
|
+
|
|
32
|
+
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:
|
|
33
|
+
|
|
34
|
+
- Specify a _default value_ for the prop if it's omitted.
|
|
35
|
+
- _Validate_ the value of the prop based on certain criteria.
|
|
36
|
+
- Mark the prop as _required_.
|
|
37
|
+
- Apply a `cast` function to modify the value passed as a prop.
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
export default Blits.Component('MyComponent', {
|
|
44
|
+
// ...
|
|
45
|
+
props: [
|
|
46
|
+
'color',
|
|
47
|
+
{
|
|
48
|
+
key: 'alpha',
|
|
49
|
+
default: 0.5,
|
|
50
|
+
required: true,
|
|
51
|
+
validate(v) {
|
|
52
|
+
return v <= 1 && v >= 0;
|
|
53
|
+
},
|
|
54
|
+
cast: Number
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
})
|
|
58
|
+
```
|
|
@@ -2,69 +2,74 @@
|
|
|
2
2
|
|
|
3
3
|
## Handling User Input
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
In order to allow users to interact with your app, you will want to capture and handle _user input_. If you are developing a TV based app this will
|
|
6
|
+
often be key input via a remote control.
|
|
6
7
|
|
|
7
|
-
Blits offers an intuitive and straightforward interface to handle key input in
|
|
8
|
+
Blits offers an intuitive and straightforward interface to handle key input in Components.
|
|
8
9
|
|
|
9
10
|
### Focus
|
|
10
11
|
|
|
11
|
-
Before diving into the specifics of key handling, it is important to understand the concept of _focus_.
|
|
12
|
+
Before diving into the specifics of key handling, it is important to understand the basic concept of _focus_.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
In a Blits app, there is always _one_ Component that has the focus. By default this will be the root Application component.
|
|
15
|
+
|
|
16
|
+
The component that has focus, is the one that is responsible for handling the user input at that moment.
|
|
17
|
+
|
|
18
|
+
For example, when a user clicks the _right_ or _left_ button while a _Poster Component_ has focus, it is that instance of the Poster Component that will _receive_ the first key press event.
|
|
14
19
|
|
|
15
20
|
### Configuring Input Handling
|
|
16
21
|
|
|
17
22
|
Within the Component configuration object, the `input` key is used to define how the component should react to specific key presses when it has focus. The `input` key should be an `object literal` of `functions` for each input event that the component wants to handle.
|
|
18
23
|
|
|
19
|
-
Each function corresponds to a _key name_, such as `up`, `down`, `enter`, `space`, `back`, `1`, `2`, `a` etc
|
|
24
|
+
Each function corresponds to a _key press name_, such as `up`, `down`, `enter`, `space`, `back`, `1`, `2`, `a` etc and each function defined in the `input` object, receives the full `InputEvent` object as its first argument.
|
|
20
25
|
|
|
21
|
-
```
|
|
26
|
+
```js
|
|
22
27
|
export default Blits.Component('MyComponent', {
|
|
23
28
|
// ...
|
|
24
29
|
input: {
|
|
25
|
-
up() {
|
|
30
|
+
up(e) {
|
|
26
31
|
// Logic to execute when users press up
|
|
27
32
|
},
|
|
28
|
-
down() {
|
|
33
|
+
down(e) {
|
|
29
34
|
// Logic to execute when users press down
|
|
30
35
|
},
|
|
31
|
-
enter() {
|
|
36
|
+
enter(e) {
|
|
32
37
|
// Logic to execute when users press enter
|
|
33
38
|
},
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
41
|
```
|
|
37
42
|
|
|
38
|
-
###
|
|
39
|
-
|
|
40
|
-
If the currently focused component does not handle a key press, Blits will traverse up the component hierarchy, checking for any _parent_ component that does have a function defined for that key press in the `input`-key. This input event handling chain continues until it reaches the root App component.
|
|
43
|
+
### Catch-All Handling
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
To allow a focused component to respond to any key and act as a _catch-all_, you can add an `any()` function to the input object. As it receives the `InputEvent` object as the first argument, you can abstract the key press in there and handle (or ignore) it as you wish.
|
|
43
46
|
|
|
44
47
|
```javascript
|
|
45
48
|
{
|
|
46
49
|
input: {
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
this.parent.focus();
|
|
50
|
-
},
|
|
51
|
-
back(e) {
|
|
52
|
-
// Give focus to the parent and let the user input event bubble
|
|
53
|
-
this.parent.focus(e);
|
|
50
|
+
any(e) {
|
|
51
|
+
// Logic to execute for any key press
|
|
54
52
|
},
|
|
55
53
|
}
|
|
56
54
|
}
|
|
57
55
|
```
|
|
58
56
|
|
|
59
|
-
###
|
|
57
|
+
### Event Handling Chain
|
|
60
58
|
|
|
61
|
-
|
|
59
|
+
If the currently focused component does not handle a key press, Blits will traverse up the component hierarchy, checking for any _parent_ component that does have a function defined for that key press in the `input`-key. This input event handling chain continues until it reaches the root Application component.
|
|
60
|
+
|
|
61
|
+
When a component handles a key press by having a corresponding function specified, said component receives focus, and the event handling chain stops by default. However, if you want the input event to propagate up the hierarchy further, you can move the focus to the parent element and pass the `InputEvent` object on in that function call.
|
|
62
62
|
|
|
63
63
|
```javascript
|
|
64
64
|
{
|
|
65
65
|
input: {
|
|
66
|
-
|
|
67
|
-
//
|
|
66
|
+
enter() {
|
|
67
|
+
// Give focus to the parent
|
|
68
|
+
this.parent.focus();
|
|
69
|
+
},
|
|
70
|
+
back(e) {
|
|
71
|
+
// Give focus to the parent and let the user input event bubble
|
|
72
|
+
this.parent.focus(e);
|
|
68
73
|
},
|
|
69
74
|
}
|
|
70
75
|
}
|
|
@@ -78,9 +83,9 @@ But it's possible that the keycodes and mapping of your target device are slight
|
|
|
78
83
|
|
|
79
84
|
In Blits you can easily configure the key mapping to match your needs. In the `src/index.js` file where we instaniate the App via the `Blits.Launch` function, we can add an extra key, called `keys`, to the _settings object_.
|
|
80
85
|
|
|
81
|
-
The `
|
|
86
|
+
The `keys` item should be an object literal, where you map a `key` or `keyCode` (from the `KeyboardEvent`) to an event name that you can use in your Components.
|
|
82
87
|
|
|
83
|
-
> You can use a site like [keyjs.dev](https://keyjs.dev/) to find the key and keyCode
|
|
88
|
+
> You can use a site like [keyjs.dev](https://keyjs.dev/) to find the appropriate key and keyCode for your device
|
|
84
89
|
|
|
85
90
|
```js
|
|
86
91
|
// src/index.js
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Blits - Lightning 3 App Development Framework
|
|
2
|
+
|
|
3
|
+
## Watchers
|
|
4
|
+
|
|
5
|
+
In some cases, you may want to execute specific actions whenever the value of a state variable, a prop, or a computed property changes. These actions could involve dispatching an event or updating another state variable.
|
|
6
|
+
|
|
7
|
+
You might be tempted to handle this functionality inside a computed property, but this is not recommended. Computed properties should not have side effects, to prevent the risk of falling into and endless loop.
|
|
8
|
+
|
|
9
|
+
Instead, Blits allows you to specify **watchers** to trigger functionality when certain variables change.
|
|
10
|
+
|
|
11
|
+
### Using Watchers
|
|
12
|
+
|
|
13
|
+
Within the `watch` key of the _Component configuration object_, you can define an object of _watcher functions_.
|
|
14
|
+
|
|
15
|
+
The name of each function should correspond with the name of the state variable, the prop, or the computed property that you want to observe. Whenever the value of the observed target changes, the respective watcher function will be invoked.
|
|
16
|
+
|
|
17
|
+
The watcher function receives two arguments: the _new value_ and the _old value_ of the observed property. This allows you to perform specific actions based on the changes.
|
|
18
|
+
|
|
19
|
+
```javascript
|
|
20
|
+
{
|
|
21
|
+
state() {
|
|
22
|
+
return {
|
|
23
|
+
alpha: 0.2
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
watch: {
|
|
27
|
+
alpha(value, oldValue) {
|
|
28
|
+
if(value > oldValue) {
|
|
29
|
+
// Execute some logic when the 'alpha' value increases
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
In this example, whenever the value of state variable `alpha` changes, the `alpha` watcher function will be invoked. The function checks if the new value is greater than the old value and executes custom logic accordingly.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Blits - Lightning 3 App Development Framework
|
|
2
|
+
|
|
3
|
+
## Application root
|
|
4
|
+
|
|
5
|
+
Every Blits App starts with a base Application component.
|
|
6
|
+
|
|
7
|
+
Ultimately this Application is a component like any regular Blits component. But it is augmented with some extra functionality. `Blits.Application` is responsible for setting up the listeners for keyhandling for example.
|
|
8
|
+
|
|
9
|
+
You can only have 1 Application component per App. By default this file is named `App.js` and it is placed in the root of the `src`-folder.
|
|
10
|
+
|
|
11
|
+
`src/App.js` will look something like this:
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
import Blits from '@lightningjs/blits'
|
|
15
|
+
|
|
16
|
+
export default Blits.Application({
|
|
17
|
+
template: `
|
|
18
|
+
<Element></Element>
|
|
19
|
+
`,
|
|
20
|
+
})
|
|
21
|
+
```
|
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
# Blits - Lightning 3 App Development Framework
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Components
|
|
4
|
+
|
|
5
|
+
Like any modern front-end framework, Blits is built around the concept of Components. Components allow you to split the UI of your App into
|
|
6
|
+
reusable pieces of code and logic.
|
|
7
|
+
|
|
8
|
+
As you get started building your App, you're free to put all your elements and logic right in the root Application component.
|
|
9
|
+
This is great for quickly playing around with Blits and Lightning.
|
|
10
|
+
|
|
11
|
+
But soon you'll find that it's beneficial to start organizing the different parts of your App into separate components. Blits Components can be nested into a tree of components.
|
|
4
12
|
|
|
5
13
|
Components in Blits follow a clearly defined structure, which helps keep your code clean and guides you to quickly build your components.
|
|
6
14
|
|
|
7
|
-
This universal structure is also valuable for
|
|
15
|
+
This universal structure is also valuable for creating drop-in components that can be easily shared across projects.
|
|
8
16
|
|
|
9
17
|
### Creating a new Component
|
|
10
18
|
|
|
11
19
|
Let's see how to create a new component and explore the basic anatomy of a component.
|
|
12
20
|
|
|
13
|
-
A new component is created using the `Blits.Component()` function. This function accepts two arguments:
|
|
21
|
+
A new component is created using the `Blits.Component()` function that is exported from the `@lightningjs/blits` package. This function accepts two arguments:
|
|
14
22
|
|
|
15
|
-
|
|
23
|
+
- The first argument is the _name_ of the component. This name will be used in debug log messages, so make sure to choose a unique and descriptive name for your component, such as `Homepage`, `Loader` or `SidebarMenuItem`.
|
|
16
24
|
|
|
17
|
-
|
|
25
|
+
- The second argument is a _Component configuration object_, represented as an `object literal`. This Component configuration object can contain a predefined set of key-value pairs, that defines how your Component looks and behaves.
|
|
26
|
+
|
|
27
|
+
Some of the common used Component configuration options include:
|
|
18
28
|
|
|
19
29
|
- `template`: to define the template for the component.
|
|
20
30
|
- `state`: to specify the component instance's internal state.
|
|
@@ -23,6 +33,8 @@ A new component is created using the `Blits.Component()` function. This function
|
|
|
23
33
|
- `input`: used to tap into user input.
|
|
24
34
|
- `methods`: used to define more complex functionality of the component
|
|
25
35
|
|
|
36
|
+
A basic Blits component will then look something like this:
|
|
37
|
+
|
|
26
38
|
```js
|
|
27
39
|
// src/components/Loader.js
|
|
28
40
|
export default Blits('Loader', {
|