@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.
@@ -25,6 +25,12 @@ import Settings from '../../settings.js'
25
25
  // temporary counter to work around shader caching issues
26
26
  let counter = 0
27
27
 
28
+ /**
29
+ * Creates a padding object from a value and direction.
30
+ * @param {number|object|string|undefined} padding - The padding value.
31
+ * @param {string} direction - The layout direction ('vertical' or 'horizontal').
32
+ * @returns {{start: number, end: number, oppositeStart: number, oppositeEnd: number}} The padding object.
33
+ */
28
34
  const createPaddingObject = (padding, direction) => {
29
35
  if (padding === undefined) {
30
36
  return { start: 0, end: 0, oppositeStart: 0, oppositeEnd: 0 }
@@ -67,6 +73,11 @@ const createPaddingObject = (padding, direction) => {
67
73
  return { start: 0, end: 0, oppositeStart: 0, oppositeEnd: 0 }
68
74
  }
69
75
 
76
+ /**
77
+ * Layout function for arranging children in a layout container.
78
+ * @param {object} config - The layout configuration object.
79
+ * @this {import('../../component.js').BlitsElement}
80
+ */
70
81
  const layoutFn = function (config) {
71
82
  const position = config.direction === 'vertical' ? 'y' : 'x'
72
83
  const oppositePosition = config.direction === 'vertical' ? 'x' : 'y'
@@ -135,18 +146,40 @@ const layoutFn = function (config) {
135
146
  }
136
147
  }
137
148
 
149
+ /**
150
+ * Checks if a value is a transition object.
151
+ * @param {any} value - The value to check.
152
+ * @returns {boolean} True if the value is a transition object, false otherwise.
153
+ */
138
154
  const isTransition = (value) => {
139
155
  return value !== null && typeof value === 'object' && 'transition' in value === true
140
156
  }
141
157
 
158
+ /**
159
+ * Checks if a string is an object string (starts and ends with curly braces).
160
+ * @param {string} str - The string to check.
161
+ * @returns {boolean} True if the string is an object string, false otherwise.
162
+ */
142
163
  const isObjectString = (str) => {
143
164
  return typeof str === 'string' && str.startsWith('{') && str.endsWith('}')
144
165
  }
145
166
 
167
+ /**
168
+ * Parses a string into an object, converting single quotes to double and adding quotes to keys.
169
+ * @param {string} str - The string to parse.
170
+ * @returns {object} The parsed object.
171
+ */
146
172
  const parseToObject = (str) => {
147
173
  return JSON.parse(str.replace(/'/g, '"').replace(/([\w-_]+)\s*:/g, '"$1":'))
148
174
  }
149
175
 
176
+ /**
177
+ * Parses a percentage string or returns the value as-is.
178
+ * @param {string|number} v - The value to parse (may be a percentage string).
179
+ * @param {string} base - The base property name ('width' or 'height').
180
+ * @returns {number|string} The parsed value as a number or the original value.
181
+ * @this {{ element: { config: { parent?: { node?: Record<string, number> } } } }}
182
+ */
150
183
  const parsePercentage = function (v, base) {
151
184
  if (typeof v !== 'string') {
152
185
  return v
@@ -160,6 +193,11 @@ const parsePercentage = function (v, base) {
160
193
  return v
161
194
  }
162
195
 
196
+ /**
197
+ * Unpacks a transition value from an object or returns the value as-is.
198
+ * @param {any} v - The value to unpack.
199
+ * @returns {any} The unpacked value.
200
+ */
163
201
  const unpackTransition = (v) => {
164
202
  if (typeof v !== 'object' || v === null) return v
165
203
  if (v.constructor === Object) {
@@ -180,8 +218,18 @@ const colorMap = {
180
218
  right: 'colorRight',
181
219
  }
182
220
 
221
+ /**
222
+ * Default text settings for text nodes (initialized on first use).
223
+ * @type {object|null}
224
+ */
183
225
  let textDefaults = null
184
226
 
227
+ /**
228
+ * @typedef {import('../../component.js').BlitsElement} BlitsElement
229
+ *
230
+ * This is always a BlitsElement
231
+ * @this {BlitsElement} this
232
+ */
185
233
  const propsTransformer = {
186
234
  set parent(v) {
187
235
  this.props['parent'] = v === 'root' ? renderer.root : v.node
@@ -333,34 +381,12 @@ const propsTransformer = {
333
381
  v[i].props.color = colors.normalize(v[i].props.color)
334
382
  }
335
383
  }
336
- const effectNames = {}
337
384
  if (this.element.node === undefined) {
338
- this.element.effectNames = []
339
385
  this.props['shader'] = renderer.createShader('DynamicShader', {
340
386
  effects: v.map((effect) => {
341
- let name = effect.type
342
- if (effectNames[name] !== undefined) {
343
- name += ++effectNames[name]
344
- } else {
345
- effectNames[name] = 1
346
- }
347
- name += this.element.counter
348
- this.element.effectNames.push(name)
349
- // temporary add counter to work around shader caching issues
350
- return renderer.createEffect(effect.type, effect.props, name)
387
+ return renderer.createEffect(effect.type, effect.props)
351
388
  }),
352
389
  })
353
- } else {
354
- for (let i = 0; i < v.length; i++) {
355
- const name = this.element.effectNames[i]
356
- // temporary add counter to work around shader caching issues
357
- const target = this.element.node.shader.props[name]
358
- const props = Object.keys(v[i].props)
359
- if (target == undefined) continue
360
- for (let j = 0; j < props.length; j++) {
361
- target[props[j]] = v[i].props[props[j]]
362
- }
363
- }
364
390
  }
365
391
  },
366
392
  set clipping(v) {
@@ -448,6 +474,10 @@ const propsTransformer = {
448
474
  }
449
475
 
450
476
  const Element = {
477
+ /**
478
+ * Populates the element with data
479
+ * @param {import('../../component.js').BlitsElementProps} data
480
+ */
451
481
  populate(data) {
452
482
  const props = data
453
483
  props['node'] = this.config.node
@@ -459,6 +489,7 @@ const Element = {
459
489
  this.props.element = this
460
490
 
461
491
  this.props['parent'] = props['parent'] || this.config.parent
492
+ //@ts-ignore This might be a left over from the old code?
462
493
  delete props.parent
463
494
 
464
495
  this.props.raw = data
@@ -506,12 +537,24 @@ const Element = {
506
537
  })
507
538
  }
508
539
  },
540
+ /**
541
+ * Set an individual property on the node
542
+ *
543
+ * @this {import('../../component').BlitsElement} this
544
+ *
545
+ * @param {import('../..//component.js').BlitsElementProps} prop
546
+ * @param {any} value
547
+ * @returns {void}
548
+ */
509
549
  set(prop, value) {
510
550
  if (value === undefined) return
551
+ // @ts-ignore
511
552
  if (this.props.raw[prop] === value) return
553
+ // @ts-ignore
512
554
  this.props.raw[prop] = value
513
555
 
514
556
  this.props.props = {}
557
+ // @ts-ignore
515
558
  this.props[prop] = unpackTransition(value)
516
559
 
517
560
  const propsKeys = Object.keys(this.props.props)
@@ -609,7 +652,7 @@ const Element = {
609
652
  return
610
653
  }
611
654
  // fire transition end callback when animation ends (if specified)
612
- if (transition.end && typeof transition.end === 'function') {
655
+ if (this.node !== undefined && transition.end && typeof transition.end === 'function') {
613
656
  transition.end.call(this.component, this, prop, this.node[prop])
614
657
  }
615
658
  // remove the prop from scheduled transitions
@@ -622,9 +665,7 @@ const Element = {
622
665
  destroy() {
623
666
  if (this.node === null) return
624
667
 
625
- Log.debug('Deleting Node', this.nodeId)
626
- this.node.destroy()
627
-
668
+ Log.debug('Deleting Node', this.nodeId)
628
669
  // Clearing transition end callback functions
629
670
  const transitionProps = Object.keys(this.scheduledTransitions)
630
671
  for (let i = 0; i < transitionProps.length; i++) {
@@ -635,7 +676,32 @@ const Element = {
635
676
  }
636
677
  }
637
678
 
638
- // remove node reference
679
+ // not setting to null and deleting,
680
+ // because transition stopped might still be fired (maybe a renderer fix resolves that)
681
+ this.scheduledTransitions = {}
682
+
683
+ this.component = null
684
+ delete this.component
685
+
686
+ this.config = null
687
+ delete this.config
688
+
689
+ this.counter = null
690
+ delete this.counter
691
+
692
+ this.props.raw = {}
693
+ this.props.element = null
694
+ this.props.props = null
695
+ this.props = {}
696
+ delete this.props
697
+
698
+ this.triggerLayout = null
699
+ delete this.triggerLayout
700
+
701
+ this.forComponent = null
702
+ delete this.forComponent
703
+
704
+ this.node.destroy()
639
705
  this.node = null
640
706
  },
641
707
  get nodeId() {
@@ -654,6 +720,13 @@ const Element = {
654
720
  },
655
721
  }
656
722
 
723
+ /**
724
+ * Returns a new Blits Element
725
+ *
726
+ * @param {Object} config - The configuration object for the element
727
+ * @param {import('../../component.js').BlitsComponent} component - The component to which the element belongs
728
+ * @returns {import('../../component.js').BlitsElement} - The new Blits Element
729
+ */
657
730
  export default (config, component) => {
658
731
  if (textDefaults === null) {
659
732
  textDefaults = {
@@ -666,7 +739,6 @@ export default (config, component) => {
666
739
  scheduledTransitions: {},
667
740
  config,
668
741
  component,
669
- effectNames: [],
670
742
  counter: counter++,
671
743
  })
672
744
  }
@@ -26,7 +26,8 @@ import colors from '../../lib/colors/colors.js'
26
26
  import fontLoader from './fontLoader.js'
27
27
  import shaderLoader from './shaderLoader.js'
28
28
 
29
- export let renderer = {}
29
+ /** @type {RendererMain|null} */
30
+ export let renderer = null
30
31
 
31
32
  const renderEngine = (settings) => {
32
33
  const renderMode = 'renderMode' in settings ? settings.renderMode : 'webgl'
@@ -63,6 +64,14 @@ const textureMemorySettings = (settings) => {
63
64
  }
64
65
  }
65
66
 
67
+ /**
68
+ * Launch the render engine and application
69
+ *
70
+ * @param {import('../../launch.js').BlitsAppFactory} App - Factory function that returns the application instance (extends BlitsComponent with .quit())
71
+ * @param {HTMLElement} target - The target element to render the application into
72
+ * @param {Partial<import('../../launch.js').BlitsSettings>} [settings] - The settings for the renderer
73
+ *
74
+ */
66
75
  export default (App, target, settings = {}) => {
67
76
  renderer = new RendererMain(
68
77
  {
package/src/launch.js CHANGED
@@ -20,6 +20,30 @@ import { initLog, Log } from './lib/log.js'
20
20
  import engine from './engine.js'
21
21
  import blitsPackageInfo from '../package.json' assert { type: 'json' }
22
22
 
23
+ /**
24
+ * @typedef {Object} Font
25
+ * @property {string} family - Name of the font family
26
+ * @property {string} type - Type of font (web, msdf, sdf)
27
+ * @property {string} [file] - Location to the font file
28
+ * @property {string} [json] - Location of the font map (for msdf/sdf)
29
+ * @property {string} [png] - Location of the font png (for msdf/sdf)
30
+ */
31
+ /**
32
+ * @typedef {Object} ShaderEffect
33
+ * @property {string} name
34
+ * @property {any} type
35
+ */
36
+ /**
37
+ * @typedef {Object} Shader
38
+ * @property {string} name
39
+ * @property {any} type
40
+ */
41
+
42
+ /**
43
+ * @typedef {import('@lightningjs/renderer').RendererMain} RendererMain
44
+ * @type {RendererMain}
45
+ */
46
+ // @ts-ignore - We ignore this because it will be replaced by the renderer once the app is launched
23
47
  export let renderer = {}
24
48
  export const stage = {}
25
49
 
@@ -37,6 +61,52 @@ async function rendererVersion() {
37
61
  }
38
62
  }
39
63
 
64
+ /**
65
+ * @typedef {Object} BlitsSettings
66
+ * @property {number} [w] - Width of the Application
67
+ * @property {number} [h] - Height of the Application
68
+ * @property {boolean} [multithreaded] - Whether to enable multithreaded
69
+ * @property {0|1|2|"info"|"warn"|"error"|"debug"[]} [debugLevel] - Debug level for console log messages
70
+ * @property {Font[]} [fonts] - Fonts to be used in the Application
71
+ * @property {ShaderEffect[]} [effects] - Effects to be used by DynamicShader
72
+ * @property {Shader[]} [shaders] - Shaders to be used in the application
73
+ * @property {string} [defaultFont] - Default font family to use in the Application
74
+ * @property {object} [keymap] - Custom keymapping
75
+ * @property {"Proxy"|"defineProperty"} [reactivityMode] - Mode of reactivity
76
+ * @property {"hd"|"720p"|720|"fhd"|"fullhd"|"1080p"|1080|"4k"|"2160p"|2160} [screenResolution] - Screen resolution of the device
77
+ * @property {"low"|"medium"|"high"|"retina"|number} [renderQuality] - Quality of the rendered App
78
+ * @property {number} [pixelRatio] - Custom pixel ratio of the device
79
+ * @property {number} [fpsInterval] - Interval in ms to receive FPS updates
80
+ * @property {number} [webWorkersLimit] - Maximum number of web workers
81
+ * @property {string} [canvasColor] - Background color of the canvas
82
+ * @property {boolean} [inspector] - Enable inspector
83
+ * @property {number|[number,number,number,number]} [viewportMargin] - Extra margin to the viewport
84
+ * @property {number} [gpuMemoryLimit] - Threshold after which textures are freed (deprecated)
85
+ * @property {object} [gpuMemory] - Configures the gpu memory settings
86
+ * @property {"webgl"|"canvas"} [renderMode] - Defines which mode the renderer should operate in
87
+ * @property {number} [holdTimeout] - Time after which a key press is considered a hold
88
+ * @property {HTMLCanvasElement} [canvas] - Custom canvas object used to render the App
89
+ * @property {number} [textureProcessingTimeLimit] - Max time renderer can process textures in a frame
90
+ * @property {Partial<import('@lightningjs/renderer').RendererMainSettings>} [advanced] - Advanced renderer settings
91
+ * @property {boolean} [announcer] - Whether or not the announcer should be activated on initialization
92
+ */
93
+
94
+ /**
95
+ * Blits App defines the structure of the Blits application.
96
+ * @typedef {import('./component').BlitsComponent} BlitsComponent
97
+ * @typedef {BlitsComponent & { quit: () => void }} BlitsAppComponent
98
+ * @typedef {() => BlitsAppComponent} BlitsAppFactory
99
+ */
100
+
101
+ /**
102
+ * Launches the Blits application with the given App, target, and settings.
103
+ * Sets up logging, version info, and initializes the renderer and stage singletons.
104
+ *
105
+ * @param {BlitsAppFactory} App - The root BlitsComponent to launch.
106
+ * @param {HTMLElement} target - The DOM element or rendering target.
107
+ * @param {BlitsSettings} settings - Configuration settings for the application.
108
+ * @returns {void}
109
+ */
40
110
  export default (App, target, settings) => {
41
111
  Settings.set(settings)
42
112
 
@@ -511,6 +511,7 @@ const generateForLoopCode = function (templateObject, parent) {
511
511
  }
512
512
  effect(eff${index}, ${key})
513
513
  effects.push(eff${index})
514
+ component[Symbol.for('effects')].push(eff${index})
514
515
  `)
515
516
  } else {
516
517
  // props shouldn't be wrapped in an effect, but simply passed on
@@ -562,17 +563,21 @@ const generateForLoopCode = function (templateObject, parent) {
562
563
 
563
564
  ctx.renderCode.push(`
564
565
  let forEffects${forStartCounter}
565
- effect(() => {
566
+ const eff${forStartCounter} = () => {
566
567
  component[Symbol.for('removeGlobalEffects')](forEffects${forStartCounter})
567
568
  forEffects${forStartCounter} = null
568
569
  forEffects${forStartCounter} = forloop${forStartCounter}(${cast(
569
570
  result[2],
570
571
  ':for'
571
572
  )}, elms, created${forStartCounter})
572
- }, ['${effectKey}', ${effectKeys.join(',')}] )
573
+ }
574
+
575
+ component[Symbol.for('effects')].push(eff${forStartCounter})
576
+
577
+ effect(eff${forStartCounter}, ['${effectKey}', ${effectKeys.join(',')}] )
573
578
  `)
574
579
 
575
- outerScopeEffects.forEach((effect) => {
580
+ outerScopeEffects.forEach((effect, outerScopeEffectsIndex) => {
576
581
  const matches = [...effect.matchAll(scopeRegex)]
577
582
 
578
583
  let l = matches.length
@@ -589,7 +594,7 @@ const generateForLoopCode = function (templateObject, parent) {
589
594
  }
590
595
 
591
596
  ctx.renderCode.push(`
592
- effect(() => {
597
+ const eff${forStartCounter}_${outerScopeEffectsIndex} = () => {
593
598
  void ${refs.join(', ')}
594
599
  for(let __index = 0; __index < ${interpolate(result[2])}.length; __index++) {
595
600
  if(__index < from${forStartCounter} || __index >= to${forStartCounter}) continue
@@ -602,7 +607,9 @@ const generateForLoopCode = function (templateObject, parent) {
602
607
  ctx.renderCode.push(`
603
608
  ${effect}
604
609
  }
605
- })
610
+ }
611
+ component[Symbol.for('effects')].push(eff${forStartCounter}_${outerScopeEffectsIndex})
612
+ effect(eff${forStartCounter}_${outerScopeEffectsIndex})
606
613
  `)
607
614
  })
608
615
 
@@ -18,18 +18,31 @@
18
18
  const counters = {}
19
19
  let counter = 0
20
20
 
21
+ /**
22
+ * Creates a human-readable component ID string for a given component name.
23
+ *
24
+ * @param {string} name - The name of the component.
25
+ * @returns {string} The generated human-readable component ID.
26
+ */
21
27
  export const createHumanReadableId = (name) => {
22
28
  return `BlitsComponent::${name}_${(counters[name] = (counters[name] || 0) + 1)}`
23
29
  }
24
30
 
31
+ /**
32
+ * Generates a new unique internal numeric ID.
33
+ *
34
+ * @returns {number} The next unique internal ID.
35
+ */
25
36
  export const createInternalId = () => {
26
37
  return ++counter
27
38
  }
28
39
 
29
40
  /**
30
- * Resets the counter value back to 0.
41
+ * Resets the internal counter value back to 0.
31
42
  * Used in automated tests to ensure consistent results, not intended
32
43
  * to be used in the actual framework code!
44
+ *
45
+ * @returns {void}
33
46
  */
34
47
  export const resetCounter = () => {
35
48
  counter = 0
@@ -19,6 +19,15 @@ const eventsMap = new Map()
19
19
  const callbackCache = new Map()
20
20
 
21
21
  export default {
22
+ /**
23
+ * Registers a listener callback for a specific event on a component.
24
+ *
25
+ * @param {object} component - The component instance to register the listener for.
26
+ * @param {string} event - The name of the event to listen for.
27
+ * @param {Function} cb - The callback function to execute when the event is emitted.
28
+ * @param {number} [priority=0] - The priority of the listener (higher runs first).
29
+ * @returns {void}
30
+ */
22
31
  registerListener(component, event, cb, priority = 0) {
23
32
  let componentsMap = eventsMap.get(event)
24
33
  if (componentsMap === undefined) {
@@ -36,6 +45,13 @@ export default {
36
45
  callbackCache.delete(event) // Invalidate the callbackCache when a new callback is added
37
46
  },
38
47
 
48
+ /**
49
+ * Deregisters a listener for a specific event on a component.
50
+ *
51
+ * @param {object} component - The component instance to deregister the listener for.
52
+ * @param {string} event - The name of the event to stop listening for.
53
+ * @returns {void}
54
+ */
39
55
  deregisterListener(component, event) {
40
56
  let componentsMap = eventsMap.get(event)
41
57
  if (componentsMap === undefined) {
@@ -49,6 +65,13 @@ export default {
49
65
  }
50
66
  },
51
67
 
68
+ /**
69
+ * Executes all registered listeners for a given event, in priority order.
70
+ *
71
+ * @param {string} event - The name of the event to emit.
72
+ * @param {any} params - The parameters to pass to the event listeners.
73
+ * @returns {boolean} True if all listeners executed without stopping propagation, false if any listener returned false.
74
+ */
52
75
  executeListeners(event, params) {
53
76
  const componentsMap = eventsMap.get(event)
54
77
  if (componentsMap === undefined || componentsMap.size === 0) {
@@ -78,6 +101,12 @@ export default {
78
101
  return true // All listeners executed without stopping propagation
79
102
  },
80
103
 
104
+ /**
105
+ * Removes all listeners for a given component from all events.
106
+ *
107
+ * @param {object} component - The component instance to remove listeners for.
108
+ * @returns {void}
109
+ */
81
110
  removeListeners(component) {
82
111
  for (const [event, componentsMap] of eventsMap) {
83
112
  if (componentsMap.has(component)) {
package/src/lib/hooks.js CHANGED
@@ -19,15 +19,36 @@ import symbols from './symbols.js'
19
19
 
20
20
  const cbs = {}
21
21
 
22
+ /**
23
+ * Emits a registered hook for a given identifier, calling the hook with the provided scope and data.
24
+ *
25
+ * @param {string|symbol} hook - The name or symbol of the hook to emit.
26
+ * @param {string} identifier - The unique identifier for the hook set.
27
+ * @param {object} scope - The value of `this` inside the hook function.
28
+ * @param {Array} [data=[]] - Arguments to pass to the hook function.
29
+ */
22
30
  export const emit = (hook, identifier, scope, data = []) => {
23
31
  cbs[identifier] && cbs[identifier][hook] && cbs[identifier][hook].apply(scope, data)
24
32
  }
25
33
 
34
+ /**
35
+ * Emits a registered symbol-based hook for a given identifier, calling the hook with the provided scope.
36
+ *
37
+ * @param {string|symbol} hook - The name or symbol of the hook to emit (will be mapped to a symbol).
38
+ * @param {string} identifier - The unique identifier for the hook set.
39
+ * @param {object} scope - The value of `this` inside the hook function.
40
+ */
26
41
  export const privateEmit = (hook, identifier, scope) => {
27
42
  const symHook = symbols[hook]
28
43
  cbs[identifier] && cbs[identifier][symHook] && cbs[identifier][symHook].apply(scope)
29
44
  }
30
45
 
46
+ /**
47
+ * Registers a set of hooks (functions) for a given identifier.
48
+ *
49
+ * @param {Object<string,Function>|Object<symbol,Function>} hooks - An object whose keys are hook names or symbols and values are functions.
50
+ * @param {string} identifier - The unique identifier for the hook set.
51
+ */
31
52
  export const registerHooks = (hooks = {}, identifier) => {
32
53
  cbs[identifier] = {}
33
54
  // Combines enumerable keys and symbol properties of the 'hooks' object
@@ -19,6 +19,10 @@ import { Log } from './log.js'
19
19
  import { emit, privateEmit } from './hooks.js'
20
20
  import symbols from './symbols.js'
21
21
 
22
+ /**
23
+ * List of valid lifecycle states for a component.
24
+ * @type {Array<string>}
25
+ */
22
26
  const states = [
23
27
  'init', // fired upon component instantiation
24
28
  'ready', // fired when component instantiated, reactivity setup done and template spawned
@@ -31,12 +35,40 @@ const states = [
31
35
  'exit', // fired when leaving the visible viewport
32
36
  ]
33
37
 
38
+ /**
39
+ * Lifecycle state manager for components.
40
+ *
41
+ * @typedef {Object} Lifecycle
42
+ * @property {string|null} previous - The previous lifecycle state.
43
+ * @property {string|null} current - The current lifecycle state.
44
+ * @property {Object} [component] - The component instance this lifecycle belongs to.
45
+ * @property {string|null} state - The current lifecycle state (getter/setter).
46
+ */
47
+
48
+ /**
49
+ * Lifecycle state management object for components.
50
+ * Handles state transitions and emits corresponding hooks.
51
+ *
52
+ * @type {Lifecycle}
53
+ * @this {Lifecycle & {component: Object}}
54
+ * The 'component' property is expected to be set by the component instance at runtime.
55
+ */
34
56
  export default {
35
57
  previous: null,
36
58
  current: null,
59
+ /**
60
+ * Gets the current lifecycle state.
61
+ * @this {Lifecycle & {component: Object}}
62
+ * @returns {string|null}
63
+ */
37
64
  get state() {
38
65
  return this.current
39
66
  },
67
+ /**
68
+ * Sets the lifecycle state and emits hooks if the state is valid and changed.
69
+ * @this {Lifecycle & {component: Object}}
70
+ * @param {string} v - The new lifecycle state.
71
+ */
40
72
  set state(v) {
41
73
  if (states.indexOf(v) > -1 && (v !== this.current || v === 'focus')) {
42
74
  Log.debug(
package/src/lib/log.js CHANGED
@@ -19,6 +19,10 @@ import Settings from '../settings.js'
19
19
 
20
20
  const n = () => {}
21
21
 
22
+ /**
23
+ * Returns the current time as a locale time string (hh:mm:ss).
24
+ * @returns {string} The current time string.
25
+ */
22
26
  const time = () =>
23
27
  new Date().toLocaleTimeString([], {
24
28
  hour: '2-digit',
@@ -26,6 +30,13 @@ const time = () =>
26
30
  second: '2-digit',
27
31
  })
28
32
 
33
+ /**
34
+ * Returns a logger object for the given context, with info, warn, debug, and error methods.
35
+ * Logging methods are no-ops if the debug level does not match.
36
+ *
37
+ * @param {string} context - The context label for log messages.
38
+ * @returns {Object} Logger object with info, warn, debug, and error methods.
39
+ */
29
40
  const logger = (context) => {
30
41
  const level = Settings.get('debugLevel')
31
42
  const log = {}
@@ -1,3 +1,55 @@
1
+ /**
2
+ * Symbol registry for internal framework properties and generated code.
3
+ *
4
+ * @typedef {Object} BlitsSymbols
5
+ * @property {symbol} currentView
6
+ * @property {symbol} cursorTagStart
7
+ * @property {symbol} computedKeys
8
+ * @property {symbol} destroy
9
+ * @property {symbol} getChildren
10
+ * @property {symbol} holder
11
+ * @property {symbol} id
12
+ * @property {symbol} identifier
13
+ * @property {symbol} index
14
+ * @property {symbol} init
15
+ * @property {symbol} inputEvents
16
+ * @property {symbol} intervals
17
+ * @property {symbol} launched
18
+ * @property {symbol} level
19
+ * @property {symbol} methodKeys
20
+ * @property {symbol} originalState
21
+ * @property {symbol} propKeys
22
+ * @property {symbol} raw
23
+ * @property {symbol} ready
24
+ * @property {symbol} renderer
25
+ * @property {symbol} routes
26
+ * @property {symbol} routerHooks
27
+ * @property {symbol} settings
28
+ * @property {symbol} state
29
+ * @property {symbol} stateKeys
30
+ * @property {symbol} textnode
31
+ * @property {symbol} timeouts
32
+ * @property {symbol} type
33
+ * @property {symbol} watchers
34
+ * @property {symbol} watchKeys
35
+ * @property {symbol} wrapper
36
+ * @property {symbol} children
37
+ * @property {symbol} components
38
+ * @property {symbol} config
39
+ * @property {symbol} isSlot
40
+ * @property {symbol} props
41
+ * @property {symbol} slots
42
+ * @property {symbol} componentType
43
+ * @property {symbol} isComponent
44
+ * @property {symbol} effects
45
+ * @property {symbol} removeGlobalEffects
46
+ */
47
+
48
+ /**
49
+ * Internal symbol registry for Blits framework and generated code.
50
+ *
51
+ * @type {BlitsSymbols}
52
+ */
1
53
  export default {
2
54
  currentView: Symbol('currentView'),
3
55
  cursorTagStart: Symbol('cursorTagStart'),
package/src/lib/utils.js CHANGED
@@ -1,3 +1,18 @@
1
+ /**
2
+ * A mapping of common screen resolution names to their scale factors relative to 1080p (Full HD).
3
+ *
4
+ * @type {Object<string|number, number>}
5
+ * @property {number} hd - 0.666... (720p)
6
+ * @property {number} '720p' - 0.666... (720p)
7
+ * @property {number} 720 - 0.666... (720p)
8
+ * @property {number} fhd - 1 (Full HD)
9
+ * @property {number} fullhd - 1 (Full HD)
10
+ * @property {number} '1080p' - 1 (Full HD)
11
+ * @property {number} 1080 - 1 (Full HD)
12
+ * @property {number} '4k' - 2 (2160p)
13
+ * @property {number} '2160p' - 2 (2160p)
14
+ * @property {number} 2160 - 2 (2160p)
15
+ */
1
16
  export const screenResolutions = {
2
17
  hd: 0.66666667,
3
18
  '720p': 0.66666667,