@lightningjs/blits 1.29.2 → 1.29.4

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,21 @@
1
1
  # Changelog
2
2
 
3
+ _03 jun 2025_
4
+
5
+ ## v1.29.4
6
+
7
+ - Removed excessive shader creation for effects
8
+ - Added explicit cleanup of effects in for loop
9
+ - Improved element destruction
10
+
11
+ _03 jun 2025_
12
+
13
+ ## v1.29.3
14
+
15
+ - Added first batch internal JS doc types
16
+ - Added documentation on Launch settings
17
+ - Fixed issue with reactivity effects being shared (and retained) on the prototype
18
+
3
19
  _28 may 2025_
4
20
 
5
21
  ## v1.29.2
@@ -0,0 +1,117 @@
1
+ # Application Settings
2
+
3
+ Blits provides a flexible and performant way to configure your application at launch using the settings object passed to `Blits.Launch`. These settings allow you to fine-tune rendering, performance, input, fonts, and more.
4
+
5
+ Below is a comprehensive overview of the available settings you can provide to a Blits Application:
6
+
7
+ ## Basic Settings
8
+
9
+ | Setting | Type | Description |
10
+ |----------------|---------------------|-------------|
11
+ | `w` | `number` | Width of the application (canvas) |
12
+ | `h` | `number` | Height of the application (canvas) |
13
+ | `debugLevel` | `number \| string[]`| Debug level for console log messages |
14
+ | `multithreaded`| `boolean` | Enable multithreaded rendering |
15
+
16
+ ## Fonts & Text
17
+
18
+ | Setting | Type | Description |
19
+ |----------------|-----------|-------------|
20
+ | `fonts` | `Font[]` | Array of font objects to register |
21
+ | `defaultFont` | `string` | Default font family to use |
22
+
23
+ Example font object:
24
+ ```js
25
+ {
26
+ family: 'lato',
27
+ type: 'msdf', // or 'web'
28
+ file: 'fonts/Lato-Regular.ttf',
29
+ }
30
+ ```
31
+
32
+ ## Rendering & Performance
33
+
34
+ | Setting | Type | Description |
35
+ |----------------|-----------|-------------|
36
+ | `renderQuality` | `'low' \| 'medium' \| 'high' \| 'retina' \| number` | Controls render quality (1 = 100%) |
37
+ | `screenResolution` | `'hd' \| 'fhd' \| '4k' \| number` | Sets device screen resolution |
38
+ | `pixelRatio` | `number` | Custom pixel ratio (overrides screenResolution) |
39
+ | `canvasColor` | `string` | Background color of the canvas |
40
+ | `fpsInterval` | `number` | Interval (ms) for FPS updates (0 disables) |
41
+ | `webWorkersLimit` | `number`| Max number of web workers for image handling |
42
+ | `gpuMemory` | `object` | GPU memory management (see below) |
43
+ | `gpuMemoryLimit`| `number` | (Deprecated) Use `gpuMemory` instead |
44
+ | `textureProcessingTimeLimit` | `number` | Max ms per frame for texture processing |
45
+ | `viewportMargin`| `number \| [number,number,number,number]` | Extra margin for preloading elements |
46
+ | `advanced` | `object` | Advanced renderer settings (use with care) |
47
+
48
+ ### GPU Memory Example
49
+ ```js
50
+ {
51
+ max: 200, // MB
52
+ target: 0.8, // 80% of max
53
+ cleanupInterval: 5000, // ms
54
+ baseline: 25, // MB
55
+ strict: false
56
+ }
57
+ ```
58
+
59
+ ## Input & Focus
60
+
61
+ | Setting | Type | Description |
62
+ |----------------|-----------|-------------|
63
+ | `keymap` | `object` | Custom key mapping for input events |
64
+ | `holdTimeout` | `number` | Time (ms) to consider a key press as hold |
65
+
66
+ ## Renderer
67
+
68
+ | Setting | Type | Description |
69
+ |----------------|-----------|-------------|
70
+ | `renderMode` | `'webgl' \| 'canvas'` | Renderer mode (default: 'webgl') |
71
+ | `canvas` | `HTMLCanvasElement` | Custom canvas to render to |
72
+
73
+ ## Effects & Shaders
74
+
75
+ | Setting | Type | Description |
76
+ |----------------|-----------|-------------|
77
+ | `effects` | `ShaderEffect[]` | Effects for DynamicShader |
78
+ | `shaders` | `Shader[]` | Custom shaders |
79
+
80
+ ## Inspector & Debugging
81
+
82
+ | Setting | Type | Description |
83
+ |----------------|-----------|-------------|
84
+ | `inspector` | `boolean` | Enable the inspector tool |
85
+
86
+ ## Accessibility
87
+
88
+ | Setting | Type | Description |
89
+ |----------------|-----------|-------------|
90
+ | `announcer` | `boolean` | Enable/disable text-to-speech announcer |
91
+
92
+ ## Example Usage
93
+
94
+ ```js
95
+ Blits.Launch(App, 'app', {
96
+ w: 1920,
97
+ h: 1080,
98
+ debugLevel: 1,
99
+ renderQuality: 'high',
100
+ fonts: [
101
+ { family: 'lato', type: 'msdf', file: 'fonts/Lato-Regular.ttf' },
102
+ ],
103
+ keymap: {
104
+ ArrowLeft: 'left',
105
+ ArrowRight: 'right',
106
+ },
107
+ gpuMemory: {
108
+ max: 200,
109
+ target: 0.8,
110
+ cleanupInterval: 5000,
111
+ baseline: 25,
112
+ strict: false,
113
+ },
114
+ inspector: false,
115
+ announcer: true,
116
+ })
117
+ ```
package/docs/sidebar.json CHANGED
@@ -42,6 +42,10 @@
42
42
  {
43
43
  "text": "Displaying text",
44
44
  "link": "/essentials/displaying_text"
45
+ },
46
+ {
47
+ "text": "Application settings",
48
+ "link": "/essentials/settings"
45
49
  }
46
50
  ]
47
51
  },
package/jsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "allowJs": true,
6
+ "checkJs": true,
7
+ "moduleResolution": "node",
8
+ "baseUrl": "./"
9
+ },
10
+ "include": ["src"],
11
+ "exclude": ["node_modules"]
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "1.29.2",
3
+ "version": "1.29.4",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.js",
6
6
  "exports": {
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "@lightningjs/msdf-generator": "^1.1.1",
50
- "@lightningjs/renderer": "^2.13.2"
50
+ "@lightningjs/renderer": "^2.13.4"
51
51
  },
52
52
  "repository": {
53
53
  "type": "git",
@@ -18,6 +18,13 @@
18
18
  import eventListeners from '../../lib/eventListeners.js'
19
19
 
20
20
  export default {
21
+ /**
22
+ * Emits an event to all registered listeners for the given event name.
23
+ *
24
+ * @param {string} event - The name of the event to emit.
25
+ * @param {any} params - The parameters to pass to the event listeners.
26
+ * @returns {boolean} True if all listeners executed, false otherwise.
27
+ */
21
28
  $emit: {
22
29
  value: function (event, params) {
23
30
  // returning if all listeners executed
@@ -27,6 +34,14 @@ export default {
27
34
  enumerable: true,
28
35
  configurable: false,
29
36
  },
37
+ /**
38
+ * Registers a listener callback for a specific event.
39
+ *
40
+ * @param {string} event - The name of the event to listen for.
41
+ * @param {Function} callback - The callback function to execute when the event is emitted.
42
+ * @param {number} [priority=0] - The priority of the listener (higher runs first).
43
+ * @returns {void}
44
+ */
30
45
  $listen: {
31
46
  value: function (event, callback, priority = 0) {
32
47
  // early exit when component is marked as end of life
@@ -37,6 +52,12 @@ export default {
37
52
  enumerable: true,
38
53
  configurable: false,
39
54
  },
55
+ /**
56
+ * Deregisters a listener for a specific event.
57
+ *
58
+ * @param {string} event - The name of the event to stop listening for.
59
+ * @returns {void}
60
+ */
40
61
  $unlisten: {
41
62
  value: function (event) {
42
63
  eventListeners.deregisterListener(this, event)
@@ -24,6 +24,9 @@ import { removeGlobalEffects } from '../../lib/reactivity/effect.js'
24
24
 
25
25
  export default {
26
26
  focus: {
27
+ /**
28
+ * @this {import('../../component').BlitsComponent}
29
+ */
27
30
  value: function (e) {
28
31
  Log.warn('this.focus is deprecated, use this.$focus instead')
29
32
  return this.$focus(e)
@@ -33,6 +36,9 @@ export default {
33
36
  configurable: false,
34
37
  },
35
38
  $focus: {
39
+ /**
40
+ * @this {import('../../component').BlitsComponent}
41
+ */
36
42
  value: function (e) {
37
43
  this[symbols.state].hasFocus = true
38
44
  Focus.set(this, e)
@@ -42,6 +48,9 @@ export default {
42
48
  configurable: false,
43
49
  },
44
50
  unfocus: {
51
+ /**
52
+ * @this {import('../../component').BlitsComponent}
53
+ */
45
54
  value: function () {
46
55
  this[symbols.state].hasFocus = false
47
56
  this.lifecycle.state = 'unfocus'
@@ -51,6 +60,9 @@ export default {
51
60
  configurable: false,
52
61
  },
53
62
  destroy: {
63
+ /**
64
+ * @this {import('../../component').BlitsComponent}
65
+ */
54
66
  value: function () {
55
67
  this.eol = true
56
68
  this.lifecycle.state = 'destroy'
@@ -94,6 +106,9 @@ export default {
94
106
  configurable: false,
95
107
  },
96
108
  [symbols.removeGlobalEffects]: {
109
+ /**
110
+ * @this {import('../../component').BlitsComponent}
111
+ */
97
112
  value: function (effects = []) {
98
113
  removeGlobalEffects(effects)
99
114
  },
@@ -102,6 +117,9 @@ export default {
102
117
  configurable: false,
103
118
  },
104
119
  select: {
120
+ /**
121
+ * @this {import('../../component').BlitsComponent}
122
+ */
105
123
  value: function (ref) {
106
124
  Log.warn('this.select is deprecated, use this.$select instead')
107
125
  return this.$select(ref)
@@ -111,6 +129,9 @@ export default {
111
129
  configurable: false,
112
130
  },
113
131
  $select: {
132
+ /**
133
+ * @this {import('../../component').BlitsComponent}
134
+ */
114
135
  value: function (ref) {
115
136
  let selected = null
116
137
  this[symbols.children].forEach((child) => {
@@ -133,6 +154,9 @@ export default {
133
154
  configurable: false,
134
155
  },
135
156
  trigger: {
157
+ /**
158
+ * @this {import('../../component').BlitsComponent}
159
+ */
136
160
  value: function (key) {
137
161
  Log.warn('this.trigger is deprecated, use this.$trigger instead')
138
162
  return this.$trigger(key)
@@ -142,6 +166,9 @@ export default {
142
166
  configurable: false,
143
167
  },
144
168
  $trigger: {
169
+ /**
170
+ * @this {import('../../component').BlitsComponent}
171
+ */
145
172
  value: function (key) {
146
173
  let target = this[symbols.originalState]
147
174
  // when dot notation used, find the nested target
@@ -160,6 +187,9 @@ export default {
160
187
  configurable: false,
161
188
  },
162
189
  shader: {
190
+ /**
191
+ * @this {import('../../component').BlitsComponent}
192
+ */
163
193
  value: function (type, args) {
164
194
  return {
165
195
  type: type,
@@ -182,6 +212,10 @@ export default {
182
212
  },
183
213
  }
184
214
 
215
+ /**
216
+ * Recursively destroys all BlitsComponent children.
217
+ * @param {import('../../component').BlitsComponent[]} children
218
+ */
185
219
  const deleteChildren = function (children) {
186
220
  for (let i = 0; i < children.length; i++) {
187
221
  if (!children[i]) return
@@ -32,8 +32,6 @@ let counter = 0
32
32
  export default function (component, config) {
33
33
  component[symbols.identifier] = ++counter
34
34
 
35
- component[symbols.effects] = []
36
-
37
35
  // setup hooks
38
36
  registerHooks(config.hooks, component[symbols.identifier])
39
37
 
package/src/component.js CHANGED
@@ -43,12 +43,150 @@ const required = (name) => {
43
43
  throw new Error(`Parameter ${name} is required`)
44
44
  }
45
45
 
46
+ /**
47
+ * @typedef {function} BlitsComponentFactory
48
+ * @param {object} opts - The options for the component instance
49
+ * @param {BlitsComponent} parentEl - The parent element for the component instance
50
+ * @param {BlitsComponent} parentComponent - The parent component for the component instance
51
+ * @param {BlitsComponent} rootComponent - The root component for the component instance
52
+ * @returns {BlitsComponent} - The component instance
53
+ */
54
+
55
+ /**
56
+ * Structure of a Blits component:
57
+ * Component:
58
+ * <Holder>
59
+ * <Wrapper>
60
+ * []<Elements>
61
+ * </Wrapper>
62
+ * </Holder>
63
+ *
64
+ * A Blits Element
65
+ * @typedef {Object} BlitsAnnouncer
66
+ * @property {(message: string) => void} assertive - Function to assertively announce a message.
67
+ * @property {() => void} clear - Function to clear the announcer.
68
+ * @property {() => void} disable - Function to disable the announcer.
69
+ * @property {() => void} enable - Function to enable the announcer.
70
+ * @property {(delay: number) => void} pause - Function to pause the announcer.
71
+ * @property {(message: string) => void} polite - Function to politely announce a message.
72
+ * @property {(message: string, politeness: 'off'|'polite'|'assertive') => void} announce - Function to announce a message with specified politeness.
73
+ * @property {() => void} stop - Function to stop the announcer.
74
+ * @property {(v: boolean) => void} toggle - Function to toggle the announcer.
75
+ *
76
+ * @typedef {Object} BlitsElementConfig
77
+ * @property {BlitsElement} parent - The parent element of this element.
78
+ * @property {any} node - The node object for the element.
79
+ *
80
+ * @typedef {Object} BlitsElementProps
81
+ * @property {boolean} __textnode - Indicates if the element is a text node.
82
+ * @property {boolean} __layout - Indicates if the element is a layout node.
83
+ * @property {BlitsElement} element - The element to which the props belong?? Do we need this?
84
+ * @property {BlitsElementConfig} config - Configuration object for the element.
85
+ * @property {Object<string, any>} props - The props object containing the properties of the element.
86
+ * @property {Object<string, any>} raw - The raw input props.
87
+ * @property {Object<string, any>} scheduledTransitions - Tracks transitions by property name.
88
+ *
89
+ * @typedef {Object} BlitsElement
90
+ * @property {BlitsComponent} component - Reference to the owning Blits component.
91
+ * @property {BlitsElementConfig} config - Configuration object for the element.
92
+ * @property {number} counter - Unique counter used for shader workarounds. FIXME?
93
+ * @property {string[]} effectNames - Names of active shader effects.
94
+ * @property {any} node - The underlying renderer node (e.g., WebGL node or text node).
95
+ * @property {BlitsElementProps} props - Proxy-like object containing transformed props.
96
+ * @property {any[]} children - WVB I cant see this populated? Filtered list of children owned by this element. FIXME?
97
+ * @property {any} parent - WVB Shortcut to the parent CoreNode?
98
+ * @property {number} nodeId - ID of the CoreNode, if available.
99
+ * @property {string|null} ref - Ref name (if defined).
100
+ * @property {function(Object):void} populate - Initializes the element with props and hooks.
101
+ * @property {function(string, any):void} set - Updates a single property.
102
+ * @property {function(string, any, Object):void} animate - Animates a property with transition options.
103
+ * @property {function():void} destroy - Destroys the underlying node and cancels transitions.
104
+ * @property {function(any): any} triggerLayout - Triggers a layout update for the element.
105
+ *
106
+ * @typedef {Object} BlitsLifecycle
107
+ * @property {BlitsComponent} component - The Blits comonent instance this lifecycle belongs to.
108
+ * @property {'init'|'ready'|'destroyed'} current - The current lifecycle state of the component.
109
+ * @property {'init'|'ready'|'destroyed'|null} previous - The previous lifecycle state of the component.
110
+ * @property {string} state - The current lifecycle state of the component.
111
+ *
112
+ * @typedef {object} BlitsComponent
113
+ * Main properties of the Blits component:
114
+ * @property {string} componentId - The unique identifier for the component instance
115
+ * @property {BlitsLifecycle} lifecycle - The lifecycle object for the component instance
116
+ * @property {BlitsComponent} parent - The parent component of the current component instance
117
+ * @property {BlitsComponent} rootParent - Reference to the root component in case of slots, otherwise this is the same as parent
118
+ * @property {BlitsComponent|BlitsElement[]} [children] - The children of the component instance
119
+ * @property {BlitsElement} [holder] - The wrapper of the entire component instance
120
+ * @property {number} [id] - The internal ID for the component instance
121
+ * @property {number} [identifier] - The identifier for the component instance WVB Whats the difference with id?
122
+ * @property {any[]} [intervals] - The intervals created by the component instance WVB Fixme
123
+ * @property {Object<string, any>} [originalState] - The original state of the component instance
124
+ * @property {Object<string, any>} [props] - The reactive properties of the component instance
125
+ * @property {any[]} [slots] - The slots of the component instance WVB Fixme
126
+ * @property {Object<string, any>} [state] - The reactive state of the component instance
127
+ * @property {any[]} [timeouts] - The timeouts created by the component instance
128
+ * @property {BlitsElement} [wrapper] - The reference to the outer element of the component instance
129
+ * @property {object} [effects] - The effects of the component instance
130
+ * @property {object} [watchers] - The watchers of the component instance
131
+ * @property {Object<string, any>} computedKeys - The computed keys of the component instance
132
+ * @property {any[]} [effects] - The effects of the component instance
133
+ * @property {string[]} [propKeys] - The keys of the props of the component instance
134
+ * @property {any[]} [stateKeys] - The keys of the state of the component instance
135
+ * Single props:
136
+ * @property {object} activeView - The active view of the component instance
137
+ * @property {boolean} hasFocus - Indicates if the component has focus
138
+ * @property {string} ref - The reference name of the component instance
139
+ * @property {number|undefined} index - The index in a for loop
140
+ * @property {number|undefined} activeRow - The active row in a for loop
141
+ * @property {string} color - The color of the component instance
142
+ * @property {number} radius - The radius of the component instance
143
+ * @property {number} size - The size of the component instance
144
+ * Methods:
145
+ * @property {function(): void} destroy - Destroys the component and its children, clearing listeners and effects.
146
+ * @property {function(any): any} focus - ⚠️ Deprecated. Use `$focus()` instead.
147
+ * @property {function(string): any} select - ⚠️ Deprecated. Use `$select(ref)` instead.
148
+ * @property {function(string, object): {type: string, props: object}} shader - Creates a shader definition object.
149
+ * @property {function(string): void} trigger - ⚠️ Deprecated. Use `$trigger(key)` instead.
150
+ * @property {function(): void} unfocus - Clears the focus state and sets lifecycle to 'unfocus'.
151
+ * Builtins:
152
+ * @property {BlitsAnnouncer} $announcer - The announcer object for the component instance
153
+ * @property {() => void} $clearTimeouts - Clears all timeouts created by the component instance
154
+ * @property {(timeoutId: number) => void} $clearTimeout - Clears all timeouts created by the component instance
155
+ * @property {() => void} $clearIntervals - Clears all intervals created by the component instance
156
+ * @property {(intervalId: number) => void} $clearInterval - Clears all intervals created by the component instance
157
+ * @property {Object} $colors - The colors object for the component instance
158
+ * @property {(event: string, params: object) => void} $emit - Emits an event with the specified parameters
159
+ * @property {function(any): void} $focus - Sets the component focus state and delegates to the Focus manager.
160
+ * @property {Object} $language - The language object for the component instance
161
+ * @property {function(any): any} $listen - The listen object for the component instance
162
+ * @property {Object} $log - The log object for the component instance
163
+ * @property {Object} $router - The router object for the component instance
164
+ * @property {function(string): any} $select - Selects a child component by `ref`.
165
+ * @property {function(any): any} $setInterval - Sets an interval for the component instance
166
+ * @property {function(any): any} $setTimeout - Sets a timeout for the component instance
167
+ * @property {function(any): any} $size - The size object for the component instance
168
+ * @property {function(any): any} $sizes - The sizes object for the component instance
169
+ * @property {function(string): void} $trigger - Forces a reactivity trigger on a property in `originalState`.
170
+ * @property {function(any): any} $unlisten - The unlisten object for the component instance
171
+ *
172
+ */
173
+
174
+ /**
175
+ * @typedef {Object} BlitsComponentConfig
176
+ * @property {string} template - The template string for the component.
177
+ * @property {function(this: BlitsComponent): Object} [state] - State factory function.
178
+ * @property {Object} [hooks] - Lifecycle hooks (frameTick, idle, attach, detach, enter, exit, etc).
179
+ * @property {Object} [code] - Compiled render/effects code (render: Function, effects: Function[]).
180
+ * @property {string} [name] - Optional name for the component.
181
+ * @property {any} [data] - Optional static data for the component.
182
+ * @property {Object} [options] - Optional options for the component.
183
+ */
184
+
46
185
  /**
47
186
  * Component factory function
48
187
  * @param {string} name - The name of the component
49
- * @param {object} config - The configuration object for the component
50
- * @returns {function} - A factory function that creates a new component instance
51
- *
188
+ * @param {BlitsComponentConfig} config - The configuration object for the component
189
+ * @returns {BlitsComponentFactory} - The component factory function
52
190
  */
53
191
  const Component = (name = required('name'), config = required('config')) => {
54
192
  let base = undefined
@@ -57,6 +195,8 @@ const Component = (name = required('name'), config = required('config')) => {
57
195
  // generate a human readable ID for the component instance (i.e. Blits::ComponentName1)
58
196
  this.componentId = createHumanReadableId(name)
59
197
 
198
+ this[symbols.effects] = []
199
+
60
200
  // instantiate a lifecycle object for this instance
61
201
  this.lifecycle = Object.assign(Object.create(Lifecycle), {
62
202
  component: this,
@@ -216,11 +356,21 @@ const Component = (name = required('name'), config = required('config')) => {
216
356
  return this
217
357
  }
218
358
 
359
+ /**
360
+ * Component factory function
361
+ * @typedef {BlitsComponentFactory}
362
+ * @param {Object} options
363
+ * @param {BlitsComponent} parentEl
364
+ * @param {BlitsComponent} parentComponent
365
+ * @param {BlitsComponent} rootComponent
366
+ * @returns {BlitsComponent}
367
+ */
219
368
  const factory = (options = {}, parentEl, parentComponent, rootComponent) => {
220
369
  if (Base[symbols['launched']] === false) {
221
370
  // Register user defined plugins once on the Base object (after launch)
222
371
  const pluginKeys = Object.keys(plugins)
223
372
  const pluginKeysLength = pluginKeys.length
373
+ /** @type {Object} */
224
374
  const pluginInstances = {}
225
375
  for (let i = 0; i < pluginKeysLength; i++) {
226
376
  const pluginName = pluginKeys[i]