@lightningjs/blits 1.10.1 → 1.12.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.
@@ -0,0 +1,27 @@
1
+ name: Trigger Website Docs Update
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ paths:
7
+ - 'docs/**'
8
+
9
+ jobs:
10
+ trigger:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Trigger Deployment
14
+ timeout-minutes: 5
15
+ run: |
16
+ response=$(curl -X POST -w "%{http_code}" -s -o /dev/null \
17
+ --max-time 30 \
18
+ --connect-timeout 10 \
19
+ --retry 2 \
20
+ --retry-delay 5 \
21
+ ${{ secrets.WEBSITE_DEPLOY_URL }})
22
+ if [ "$response" -ge 200 ] && [ "$response" -lt 300 ]; then
23
+ echo "Deployment triggered successfully"
24
+ else
25
+ echo "Failed to trigger deployment. Status code: $response"
26
+ exit 1
27
+ fi
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.12.0
4
+
5
+ - Fixed `$hasFocus` state variable not being set when navigating back to a page with `keepAlive` enabled
6
+ - Added `@updated`-event to Layout component
7
+ - Fixed issue with simple config for Theme plugin
8
+
9
+
10
+ ## v1.11.0
11
+
12
+ _19 nov 2024_
13
+
14
+ - Added support for splitting up translation file per language
15
+ - Added hasFocus property to ComponentBase type
16
+ - Fixed issue with alpha during router transitions
17
+
18
+
3
19
  ## v1.10.1
4
20
 
5
21
  _15 nov 2024_
@@ -7,6 +23,7 @@ _15 nov 2024_
7
23
  - Upgraded to renderer 2.7.1
8
24
  - Added documentation on Router
9
25
 
26
+
10
27
  ## v1.10.0
11
28
 
12
29
  _8 nov 2024_
package/blits.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /// <reference types="./index.d.ts" />
2
+
3
+ declare module '*.blits' {
4
+ const component: any;
5
+ export default component;
6
+ }
package/docs/_sidebar.md CHANGED
@@ -27,6 +27,7 @@
27
27
  - Router
28
28
  - [Basics](/router/basics.md)
29
29
  - [Hooks](/router/hooks.md)
30
+ - [Transitions](/router/transitions.md)
30
31
  - Plugins
31
32
  - [Text-to-Speech / Announcer](/plugins/text-to-speech-announcer.md)
32
33
  - [Language](/plugins/language.md)
@@ -63,7 +63,35 @@ And of course you can nest _vertical_ Layouts inside a _horizontal_ one - and vi
63
63
 
64
64
  ### Transitioning layouts
65
65
 
66
- The `<Layout>`-component can also take into account when dimensions of children change with a transition applied to it. The component will recalculate the position of its children as the transition progresses, making sure that elements are always perfectly positioned relative to one another.
66
+ The `<Layout>`-component can also take into account when dimensions of children change with a transition applied to it (i.e. `<Element :w.transition="$myWidth">`). The component will recalculate the position of its children as the transition progresses, making sure that elements are always perfectly positioned relative to one another.
67
+
68
+ ### Updated event
69
+
70
+ The `<Layout>`-tag automatically updates its dimensions based on the dimensions of its children. After each update in the children, the an `updated`-event is emitted on the `<Layout>`-tag. It will receive the current dimensions of the layout.
71
+
72
+ You can tap into this event by adding an `@updated`-attribute to the `<Layout />`-tag and refer to a method in your Component logic.
73
+
74
+
75
+ ```js
76
+ export default Blits.Component('LayoutUpdate', {
77
+ template: `
78
+ <Element>
79
+ <Layout @updated="$layoutUpdate">
80
+ <Element :w="$width" h="40" color="red" />
81
+ <Element :w="$width" h="40" color="blue" />
82
+ <Element :w="$width" h="40" color="green" />
83
+ </Layout>
84
+ </Element>
85
+ `,
86
+ methods: {
87
+ layoutUpdate(dimensions, el) {
88
+ console.log(`Layout (${el.nodeId}) dimensions updated! Width: ${dimensions.w}, Height: ${dimensions.h}`)
89
+ }
90
+ }
91
+ })
92
+ ```
93
+
94
+ > Please be aware that the `@updated` event can fire multiple times. The size of the Layout-tag is recalculated for each change in children. Also note that the `@updated` event does not guarantee a change in dimensions. It is possible that it fires for a children update, but remains the same size.
67
95
 
68
96
  ## Performance
69
97
 
@@ -75,3 +75,24 @@ The second `$`-sign is needed, since the appState plugin itself is prefixed with
75
75
 
76
76
  In order to read or update variables on the global app state inside the component logic, you can access the entire state via `this.$appState`.
77
77
 
78
+ ### Watching global state
79
+
80
+ Similar to component state, you can watch for changes in the global state as well. You can to refer to global state variables using _dot-notation_ in the watcher function name, and _prefixing_ it with `$appState`. This means that you need to define your watcher as a `String`, matching one of the examples below, depending on your style preference.
81
+
82
+ ```js
83
+ Blits.Component('MyComponent', {
84
+ template: `
85
+ <Element>
86
+ <Text :content="$$appState.loggedIn ? $$appState.user.name : 'Not logged in'" />
87
+ </Element>
88
+ `,
89
+ watch: {
90
+ '$appState.fooBar'(v, old) {
91
+ console.log(`$appState.fooBar changed from ${old} to ${v}`)
92
+ },
93
+ '$appState.my.nested.data': function(v, old) {
94
+ console.log(`My nested App state data changed!`)
95
+ }
96
+ },
97
+ })
98
+ ```
package/docs/sidebar.json CHANGED
@@ -118,6 +118,10 @@
118
118
  {
119
119
  "text": "Hooks",
120
120
  "link": "/router/hooks"
121
+ },
122
+ {
123
+ "text": "Transitions",
124
+ "link": "/router/transitions"
121
125
  }
122
126
  ]
123
127
  },
package/index.d.ts CHANGED
@@ -15,6 +15,9 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
+ // blits file type reference
19
+ /// <reference path="./blits.d.ts" />
20
+
18
21
  import {type ShaderEffect as RendererShaderEffect, type WebGlCoreShader} from '@lightningjs/renderer'
19
22
 
20
23
  declare module '@lightningjs/blits' {
@@ -149,6 +152,11 @@ declare module '@lightningjs/blits' {
149
152
  }
150
153
 
151
154
  export type ComponentBase = {
155
+ /**
156
+ * Check if a component has focus
157
+ */
158
+ hasFocus: boolean,
159
+
152
160
  /**
153
161
  * Listen to events emitted by other components
154
162
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "1.10.1",
3
+ "version": "1.12.0",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.js",
6
6
  "exports": {
@@ -30,7 +30,7 @@ const layoutFn = function (config) {
30
30
  const dimension = config.direction === 'vertical' ? 'height' : 'width'
31
31
  const oppositeDimension = config.direction === 'vertical' ? 'width' : 'height'
32
32
 
33
- const children = this.children
33
+ const children = this.node.children
34
34
  const childrenLength = children.length
35
35
  let otherDimension = 0
36
36
  const gap = config.gap || 0
@@ -53,8 +53,8 @@ const layoutFn = function (config) {
53
53
  otherDimension = Math.max(otherDimension, node[oppositeDimension])
54
54
  }
55
55
  // adjust the size of the layout container
56
- this[dimension] = offset - gap
57
- this[oppositeDimension] = otherDimension
56
+ this.node[dimension] = offset - gap
57
+ this.node[oppositeDimension] = otherDimension
58
58
 
59
59
  const align = {
60
60
  start: 0,
@@ -69,6 +69,11 @@ const layoutFn = function (config) {
69
69
  node[oppositeMount] = align
70
70
  }
71
71
  }
72
+
73
+ // emit an updated event
74
+ if (config['@updated'] !== undefined) {
75
+ config['@updated']({ w: this.node.width, h: this.node.height }, this)
76
+ }
72
77
  }
73
78
 
74
79
  const isTransition = (value) => {
@@ -363,7 +368,7 @@ const Element = {
363
368
  }
364
369
 
365
370
  if (props.__layout === true) {
366
- this.triggerLayout = layoutFn.bind(this.node)
371
+ this.triggerLayout = layoutFn.bind(this)
367
372
  }
368
373
 
369
374
  if (this.config.parent.props !== undefined && this.config.parent.props.__layout === true) {
@@ -37,22 +37,45 @@ export default {
37
37
  )
38
38
 
39
39
  const setLanguage = (language) => {
40
- // define the dictionary
41
- dictionary = translations[language] || {}
42
- // set the current language in the reactive state
43
- state.language = language
44
-
45
- // warnings
46
- if (Object.keys(translations).length === 0) {
47
- Log.warn(
48
- 'No translations loaded. Please load a file with translations or specify a translations object manually'
49
- )
50
- }
51
- if (language in translations === false) {
52
- Log.warn(`Language ${language} not available in the loaded translations`)
40
+ const warningMsg =
41
+ Object.keys(translations).length === 0
42
+ ? 'No translations loaded. Please load a file with translations or specify a translations object manually'
43
+ : language in translations === false
44
+ ? `Language ${language} not available in the loaded translations`
45
+ : false
46
+ if (warningMsg) {
47
+ Log.warn(warningMsg)
48
+ // set the current language in the reactive state
49
+ state.language = language
50
+ } else {
51
+ setDict(language).then(() => {
52
+ state.language = language
53
+ })
53
54
  }
54
55
  }
55
56
 
57
+ const setDict = (language) => {
58
+ return new Promise((resolve) => {
59
+ const translationObj = translations[language]
60
+ if (typeof translationObj === 'object') {
61
+ dictionary = translationObj
62
+ resolve()
63
+ } else if (typeof translationObj === 'string') {
64
+ fetchJson(translationObj)
65
+ .then((result) => {
66
+ // save the translations for this language (to prevent loading twice)
67
+ translations[language] = result
68
+ // define the dictionary
69
+ dictionary = result
70
+ resolve()
71
+ })
72
+ .catch((e) => {
73
+ Log.error(e)
74
+ })
75
+ }
76
+ })
77
+ }
78
+
56
79
  const loadLanguageFile = (filePath) => {
57
80
  return fetchJson(filePath)
58
81
  .then((result) => {
@@ -65,8 +88,9 @@ export default {
65
88
 
66
89
  const setTranslations = (translationsObject) => {
67
90
  translations = translationsObject
68
- dictionary = translations[state.language] || {}
69
- state.loaded++
91
+ setDict(state.language).then(() => {
92
+ state.loaded++
93
+ })
70
94
  }
71
95
 
72
96
  if ('file' in options) {
@@ -72,7 +72,7 @@ export default {
72
72
  // theme get function when current theme is modified
73
73
  state.current
74
74
  if (themeMap[key] !== undefined) return themeMap[key]
75
- const value = getValueByDotNotation(themes[state.current], themes[base], key)
75
+ const value = getValueByDotNotation(themes[state.current], themes[base] || null, key)
76
76
  if (value !== undefined) {
77
77
  // store the value for next time
78
78
  themeMap[key] = value
@@ -168,6 +168,25 @@ export const navigate = async function () {
168
168
  }
169
169
  } else {
170
170
  holder = view[symbols.holder]
171
+
172
+ // Check, whether cached view holder's alpha prop is exists in transition or not
173
+ let hasAlphaProp = false
174
+ if (route.transition.before) {
175
+ if (Array.isArray(route.transition.before)) {
176
+ for (let i = 0; i < route.transition.before.length; i++) {
177
+ if (route.transition.before[i].prop === 'alpha') {
178
+ hasAlphaProp = true
179
+ break
180
+ }
181
+ }
182
+ } else if (route.transition.before.prop === 'alpha') {
183
+ hasAlphaProp = true
184
+ }
185
+ }
186
+ // set holder alpha when alpha prop is not exists in route transition
187
+ if (hasAlphaProp === false) {
188
+ holder.set('alpha', 1)
189
+ }
171
190
  }
172
191
 
173
192
  this[symbols.children].push(view)
@@ -176,7 +195,7 @@ export const navigate = async function () {
176
195
  previousFocus = Focus.get()
177
196
 
178
197
  // set focus to the view that we're routing to
179
- focus ? Focus.set(focus) : Focus.set(view)
198
+ focus ? focus.$focus() : view.$focus()
180
199
 
181
200
  // apply before settings to holder element
182
201
  if (route.transition.before) {