@lightningjs/blits 1.35.4 → 1.36.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 CHANGED
@@ -1,6 +1,24 @@
1
1
  # Changelog
2
2
 
3
- ## v1.35.3
3
+ ## v1.36.0
4
+
5
+ _11 Aug 2025_
6
+
7
+ - Added `passFocus` option to route options to prevent focus being passed to page navigated to
8
+ - Added missing type definitions for Route options
9
+ - Fixed sidebar in docs
10
+ - Added debug log messages to Announcer
11
+ - Added `remove()` function as (preferred) alias for announcer `message.cancel()`
12
+ - Fixed issue with removing a messages causing an interrupt of current message being read out
13
+
14
+ ## v1.35.5
15
+
16
+ _06 Aug 2025_
17
+
18
+ - Fixed timing routerview causing focus to be passed to previous page
19
+
20
+
21
+ ## v1.35.4
4
22
 
5
23
  _03 Aug 2025_
6
24
 
package/index.d.ts CHANGED
@@ -187,7 +187,30 @@ declare module '@lightningjs/blits' {
187
187
 
188
188
  // todo: specify valid route options
189
189
  export interface RouteOptions {
190
- [key: string]: any
190
+ /**
191
+ * Whether the page navigation should be added to the history stack
192
+ * used when navigating back using `this.$router.back()`
193
+ *
194
+ * @default true
195
+ */
196
+ inHistory?: Boolean
197
+ /**
198
+ * Whether the page should be kept alive when navigating away. Can be useful
199
+ * for a homepage where the state should be fully retained when navigating back
200
+ * from a details page
201
+ *
202
+ * @default false
203
+ */
204
+ keepAlive?: Boolean
205
+ /**
206
+ * Whether the focus should be delegated to the page that's being navigated to.
207
+ * Can be useful when navigating to a new page from a widget / menu overlaying the
208
+ * RouterView, where the widget should maintain the focus (instead of the new page, which
209
+ * is the default behaviour)
210
+ *
211
+ * @default true
212
+ */
213
+ passFocus?: Boolean
191
214
  }
192
215
 
193
216
  export interface Router {
@@ -628,7 +651,7 @@ declare module '@lightningjs/blits' {
628
651
  /**
629
652
  * Extra route options
630
653
  */
631
- options?: object // todo: specify which options are available,
654
+ options?: RouteOptions
632
655
  /**
633
656
  * Message to be announced when visiting the route (often used for accessibility purposes)
634
657
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "1.35.4",
3
+ "version": "1.36.0",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.js",
6
6
  "exports": {
@@ -15,6 +15,7 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
+ import { Log } from '../lib/log.js'
18
19
  import speechSynthesis from './speechSynthesis.js'
19
20
 
20
21
  let active = false
@@ -28,6 +29,7 @@ const noopAnnouncement = {
28
29
  then() {},
29
30
  done() {},
30
31
  cancel() {},
32
+ remove() {},
31
33
  stop() {},
32
34
  }
33
35
 
@@ -66,11 +68,11 @@ const addToQueue = (message, politeness, delay = false) => {
66
68
  resolveFn = resolve
67
69
  })
68
70
 
69
- // augment the promise with a cancel function
70
- done.cancel = () => {
71
+ // augment the promise with a cancel / remove function
72
+ done.remove = done.cancel = () => {
71
73
  const index = queue.findIndex((item) => item.id === id)
72
74
  if (index !== -1) queue.splice(index, 1)
73
- isProcessing = false
75
+ Log.debug(`Announcer - removed from queue: "${message}" (id: ${id})`)
74
76
  resolveFn('canceled')
75
77
  }
76
78
 
@@ -92,6 +94,8 @@ const addToQueue = (message, politeness, delay = false) => {
92
94
  queue.push({ delay, resolveFn, id })
93
95
  }
94
96
 
97
+ Log.debug(`Announcer - added to queue: "${message}" (id: ${id})`)
98
+
95
99
  setTimeout(() => {
96
100
  processQueue()
97
101
  }, 100)
@@ -118,17 +122,22 @@ const processQueue = async () => {
118
122
  if (debounce !== null) clearTimeout(debounce)
119
123
  // add some easing when speaking the messages to reduce stuttering
120
124
  debounce = setTimeout(() => {
125
+ Log.debug(`Announcer - speaking: "${message}" (id: ${id})`)
126
+
121
127
  speechSynthesis
122
- .speak({ message })
128
+ .speak({ message, id })
123
129
  .then(() => {
124
- isProcessing = false
130
+ Log.debug(`Announcer - finished speaking: "${message}" (id: ${id})`)
131
+
125
132
  currentId = null
133
+ isProcessing = false
126
134
  resolveFn('finished')
127
135
  processQueue()
128
136
  })
129
137
  .catch((e) => {
130
- isProcessing = false
131
138
  currentId = null
139
+ isProcessing = false
140
+ Log.debug(`Announcer - error ("${e.error}") while speaking: "${message}" (id: ${id})`)
132
141
  resolveFn(e.error)
133
142
  processQueue()
134
143
  })
@@ -64,7 +64,7 @@ const initialize = () => {
64
64
 
65
65
  const speak = (options) => {
66
66
  const utterance = new SpeechSynthesisUtterance(options.message)
67
- const id = Date.now() + Math.random() // Unique ID for tracking
67
+ const id = options.id
68
68
  utterance.lang = options.lang || defaultUtteranceProps.lang
69
69
  utterance.pitch = options.pitch || defaultUtteranceProps.pitch
70
70
  utterance.rate = options.rate || defaultUtteranceProps.rate
@@ -18,6 +18,7 @@
18
18
  import Component from '../component.js'
19
19
  import Router from '../router/router.js'
20
20
  import symbols from '../lib/symbols.js'
21
+ import Focus from '../focus.js'
21
22
 
22
23
  let hashchangeHandler = null
23
24
 
@@ -93,7 +94,9 @@ export default () =>
93
94
  window.removeEventListener('hashchange', hashchangeHandler, false)
94
95
  },
95
96
  focus() {
96
- this.activeView && this.activeView.$focus()
97
+ if (this.activeView && Focus.get() === this) {
98
+ this.activeView.$focus()
99
+ }
97
100
  },
98
101
  },
99
102
  input: {
@@ -337,8 +337,13 @@ export const navigate = async function () {
337
337
  // keep reference to the previous focus for storing in cache
338
338
  previousFocus = Focus.get()
339
339
 
340
- // set focus to the view that we're routing to
341
- focus ? focus.$focus() : /** @type {BlitsComponent} */ (view).$focus()
340
+ const children = this[symbols.children]
341
+ this.activeView = children[children.length - 1]
342
+
343
+ // set focus to the view that we're routing to (unless explicitly disabling passing focus)
344
+ if (route.options.passFocus !== false) {
345
+ focus ? focus.$focus() : /** @type {BlitsComponent} */ (view).$focus()
346
+ }
342
347
 
343
348
  // apply before settings to holder element
344
349
  if (route.transition.before) {
@@ -380,8 +385,6 @@ export const navigate = async function () {
380
385
  await setOrAnimate(holder, route.transition.in, shouldAnimate)
381
386
  }
382
387
  }
383
- const children = this[symbols.children]
384
- this.activeView = children[children.length - 1]
385
388
  } else {
386
389
  Log.error(`Route ${hash} not found`)
387
390
  const routerHooks = this.parent[symbols.routerHooks]