@lightningjs/blits 1.50.0 → 1.51.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,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## v1.51.0
4
+
5
+ _04 mar 2026_
6
+
7
+ - Fixed wrong message from being interrupted in announcer
8
+ - Added `@loaded` and `@error` callbacks to Sprites
9
+
3
10
  ## v1.50.0
4
11
 
5
12
  _27 feb 2026_
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "1.50.0",
3
+ "version": "1.51.0",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.js",
6
6
  "exports": {
@@ -149,9 +149,11 @@ const processQueue = async () => {
149
149
  processQueue()
150
150
  })
151
151
  .catch((e) => {
152
- currentId = null
153
- currentResolveFn = null
154
- isProcessing = false
152
+ if (id === currentId) {
153
+ currentId = null
154
+ currentResolveFn = null
155
+ isProcessing = false
156
+ }
155
157
  Log.debug(`Announcer - error ("${e.error}") while speaking: "${message}" (id: ${id})`)
156
158
  resolveFn(e.error)
157
159
  processQueue()
@@ -45,6 +45,9 @@ const Application = (config) => {
45
45
  let mouseListenersAdded = false
46
46
 
47
47
  config.hooks[symbols.destroy] = function () {
48
+ // Cancel pending key-hold timeout and reset hold state so focus is not left in hold mode after teardown
49
+ clearTimeout(holdTimeout)
50
+ Focus.hold = false
48
51
  document.removeEventListener('keydown', keyDownHandler)
49
52
  document.removeEventListener('keyup', keyUpHandler)
50
53
  if (mouseListenersAdded) {
@@ -85,8 +85,7 @@ export default () =>
85
85
  ],
86
86
  context: {},
87
87
  },
88
- props: ['image', 'map', 'frame', 'color', 'effects'],
89
-
88
+ props: ['image', 'map', 'frame', 'color', 'effects', '@loaded', '@error'],
90
89
  state() {
91
90
  return {
92
91
  spriteTexture: null,
@@ -94,6 +93,33 @@ export default () =>
94
93
  }
95
94
  },
96
95
 
96
+ hooks: {
97
+ ready() {
98
+ const loaded = this['@loaded']
99
+ if (loaded && typeof loaded === 'function') {
100
+ const cb = (payload) => loaded({ w: payload?.w, h: payload?.h }, this[symbols.wrapper])
101
+ this._loadedCb = cb
102
+ if (this.spriteTexture !== undefined && this.spriteTexture !== null) {
103
+ this.spriteTexture.on('loaded', cb)
104
+ }
105
+ }
106
+ const error = this['@error']
107
+ if (error && typeof error === 'function') {
108
+ const cb = (payload) => error(payload, this[symbols.wrapper])
109
+ this._failedCb = cb
110
+ if (this.spriteTexture !== undefined && this.spriteTexture !== null) {
111
+ this.spriteTexture.on('failed', cb)
112
+ }
113
+ }
114
+ },
115
+ destroy() {
116
+ if (this.spriteTexture !== undefined && this.spriteTexture !== null) {
117
+ if (this._loadedCb) this.spriteTexture.off('loaded', this._loadedCb)
118
+ if (this._failedCb) this.spriteTexture.off('failed', this._failedCb)
119
+ }
120
+ },
121
+ },
122
+
97
123
  computed: {
98
124
  texture() {
99
125
  // If no image - nothing to render
@@ -113,10 +139,17 @@ export default () =>
113
139
  this.spriteTexture === null ||
114
140
  this.currentSrc !== this.image
115
141
  ) {
142
+ const prevTexture = this.spriteTexture
143
+ if (prevTexture !== undefined && prevTexture !== null) {
144
+ if (this._loadedCb) prevTexture.off('loaded', this._loadedCb)
145
+ if (this._failedCb) prevTexture.off('failed', this._failedCb)
146
+ }
116
147
  this.spriteTexture = renderer.createTexture('ImageTexture', {
117
148
  src: this.image,
118
149
  })
119
150
  this.currentSrc = this.image
151
+ if (this._loadedCb) this.spriteTexture.on('loaded', this._loadedCb)
152
+ if (this._failedCb) this.spriteTexture.on('failed', this._failedCb)
120
153
  }
121
154
 
122
155
  // Resolve frame data from sprite map