@lightningjs/blits 1.45.0 → 2.0.0-beta.1

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.
Files changed (38) hide show
  1. package/CHANGELOG.md +0 -11
  2. package/README.md +0 -2
  3. package/index.d.ts +23 -86
  4. package/package.json +5 -24
  5. package/scripts/prepublishOnly.js +1 -4
  6. package/src/component/base/methods.js +16 -76
  7. package/src/component/base/utils.js +18 -4
  8. package/src/component/setup/props.js +37 -28
  9. package/src/component/setup/state.js +4 -4
  10. package/src/component.js +25 -16
  11. package/src/components/Circle.js +49 -7
  12. package/src/components/FPScounter.js +226 -88
  13. package/src/components/RouterView.js +50 -5
  14. package/src/components/Sprite.js +61 -20
  15. package/src/engines/L3/element.js +109 -86
  16. package/src/engines/L3/fontLoader.js +26 -31
  17. package/src/engines/L3/shaderLoader.js +56 -6
  18. package/src/focus.js +9 -9
  19. package/src/launch.js +1 -2
  20. package/src/lib/codegenerator/generator.js +117 -16
  21. package/src/lib/colors/colors.js +0 -1
  22. package/src/lib/lifecycle.js +3 -3
  23. package/src/lib/precompiler/precompiler.js +14 -23
  24. package/src/lib/reactivityguard/computedprops.js +1 -6
  25. package/src/lib/shaders/shaders.js +163 -0
  26. package/src/lib/symbols.js +8 -0
  27. package/src/lib/templateparser/parser.js +6 -2
  28. package/src/lib/utils.js +36 -0
  29. package/src/router/router.js +7 -7
  30. package/vite/blitsTips.js +57 -0
  31. package/vite/msdfGenerator.js +52 -6
  32. package/vite/preCompiler.js +5 -15
  33. package/vscode/data/template-attributes.json +112 -0
  34. package/src/plugins/appstate.d.ts +0 -29
  35. package/src/plugins/index.d.ts +0 -29
  36. package/src/plugins/language.d.ts +0 -34
  37. package/src/plugins/storage/storage.d.ts +0 -29
  38. package/src/plugins/theme.d.ts +0 -35
@@ -25,6 +25,47 @@ export default () =>
25
25
  code: {
26
26
  render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
27
27
  const elms = []
28
+ const validAttributes = [
29
+ 'parent',
30
+ 'rotation',
31
+ 'w',
32
+ 'width',
33
+ 'h',
34
+ 'height',
35
+ 'x',
36
+ 'y',
37
+ 'z',
38
+ 'zIndex',
39
+ 'color',
40
+ 'src',
41
+ 'texture',
42
+ 'fit',
43
+ 'rtt',
44
+ 'mount',
45
+ 'pivot',
46
+ 'scale',
47
+ 'show',
48
+ 'alpha',
49
+ 'rounded',
50
+ 'border',
51
+ 'shadow',
52
+ 'shader',
53
+ 'clipping',
54
+ 'overflow',
55
+ 'font',
56
+ 'size',
57
+ 'maxwidth',
58
+ 'maxheight',
59
+ 'maxlines',
60
+ 'textoverflow',
61
+ 'letterspacing',
62
+ 'lineheight',
63
+ 'contain',
64
+ 'align',
65
+ 'content',
66
+ 'placement',
67
+ 'inspector-data',
68
+ ]
28
69
  const elementConfigs = []
29
70
  const forloops = []
30
71
  const props = []
@@ -45,8 +86,8 @@ export default () =>
45
86
  inSlot === true ? slotComponent : component
46
87
  )
47
88
 
48
- elementConfigs[0]['w'] = parent.node.width * (100 / 100)
49
- elementConfigs[0]['h'] = parent.node.height * (100 / 100)
89
+ elementConfigs[0]['w'] = parent.node.w * (100 / 100)
90
+ elementConfigs[0]['h'] = parent.node.h * (100 / 100)
50
91
  elementConfigs[0]['texture'] = component.texture
51
92
  elementConfigs[0]['color'] = component.color
52
93
  elementConfigs[0]['effects'] = component.effects
@@ -72,20 +113,25 @@ export default () =>
72
113
  props.length = 0
73
114
  skips.length = 0
74
115
  },
116
+ skips,
75
117
  }
76
118
  },
77
119
  effects: [
78
- function anonymous(component, elms, context, components, rootComponent, effect) {
120
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
79
121
  elms[0].set('texture', component.texture)
80
122
  },
81
- function anonymous(component, elms, context, components, rootComponent, effect) {
123
+ function anonymous(component, elms, context, components, rootComponent, skips, effect) {
82
124
  elms[0].set('color', component.color)
83
125
  },
84
126
  ],
85
127
  context: {},
86
128
  },
87
- props: ['image', 'map', 'frame', 'color', 'effects'],
88
-
129
+ props: {
130
+ image: undefined,
131
+ map: undefined,
132
+ frame: undefined,
133
+ color: undefined,
134
+ },
89
135
  state() {
90
136
  return {
91
137
  spriteTexture: null,
@@ -121,20 +167,15 @@ export default () =>
121
167
  // Resolve frame data from sprite map
122
168
  let options = null
123
169
  if (
124
- this.map !== null &&
125
170
  this.map !== undefined &&
126
- this.frame !== null &&
127
- this.frame !== undefined
171
+ this.map !== null &&
172
+ this.frame !== undefined &&
173
+ this.frame !== null
128
174
  ) {
129
- if (
130
- this.map.frames !== null &&
131
- this.map.frames !== undefined &&
132
- this.frame in this.map.frames
133
- ) {
134
- options = Object.assign({}, this.map.defaults || {}, this.map.frames[this.frame])
135
- } else if (this.frame in this.map) {
136
- options = this.map[this.frame]
137
- }
175
+ options =
176
+ 'frames' in this.map
177
+ ? Object.assign({}, this.map.defaults || {}, this.map.frames[this.frame])
178
+ : this.map[this.frame]
138
179
  }
139
180
 
140
181
  // If no map but frame is object (manual subtexture)
@@ -148,8 +189,8 @@ export default () =>
148
189
  texture: this.spriteTexture,
149
190
  x: options.x,
150
191
  y: options.y,
151
- width: options.w,
152
- height: options.h,
192
+ w: options.w,
193
+ h: options.h,
153
194
  })
154
195
  }
155
196
 
@@ -16,11 +16,13 @@
16
16
  */
17
17
 
18
18
  import { renderer } from './launch.js'
19
+ import { parseToObject, isObjectString, isArrayString, isTransition } from '../../lib/utils.js'
19
20
  import colors from '../../lib/colors/colors.js'
20
21
 
21
22
  import { Log } from '../../lib/log.js'
22
23
  import symbols from '../../lib/symbols.js'
23
24
  import Settings from '../../settings.js'
25
+ import shaders from '../../lib/shaders/shaders.js'
24
26
 
25
27
  /**
26
28
  * Creates a padding object from a value and direction.
@@ -79,8 +81,8 @@ const layoutFn = function (config) {
79
81
  const position = config.direction === 'vertical' ? 'y' : 'x'
80
82
  const oppositePosition = config.direction === 'vertical' ? 'x' : 'y'
81
83
  const oppositeMount = config.direction === 'vertical' ? 'mountX' : 'mountY'
82
- const dimension = config.direction === 'vertical' ? 'height' : 'width'
83
- const oppositeDimension = config.direction === 'vertical' ? 'width' : 'height'
84
+ const dimension = config.direction === 'vertical' ? 'h' : 'w'
85
+ const oppositeDimension = config.direction === 'vertical' ? 'w' : 'h'
84
86
  const padding = createPaddingObject(config.padding, config.direction)
85
87
 
86
88
  let offset = padding.start
@@ -98,17 +100,10 @@ const layoutFn = function (config) {
98
100
  node[position] = offset
99
101
  node[oppositePosition] = padding.oppositeStart
100
102
  // todo: temporary text check, due to 1px width of empty text node
101
- if (dimension === 'width') {
102
- offset += node.width + (node.width !== ('text' in node ? 1 : 0) ? gap : 0)
103
+ if (dimension === 'w') {
104
+ offset += node.w + (node.w !== ('text' in node ? 1 : 0) ? gap : 0)
103
105
  } else {
104
- offset +=
105
- 'text' in node
106
- ? node.width > 1
107
- ? node.height + gap
108
- : 0
109
- : node.height !== 0
110
- ? node.height + gap
111
- : 0
106
+ offset += 'text' in node ? (node.w > 1 ? node.h + gap : 0) : node.h !== 0 ? node.h + gap : 0
112
107
  }
113
108
  otherDimension = Math.max(
114
109
  otherDimension,
@@ -135,7 +130,7 @@ const layoutFn = function (config) {
135
130
 
136
131
  // emit an updated event
137
132
  if (config['@updated'] !== undefined) {
138
- config['@updated']({ w: this.node.width, h: this.node.height }, this)
133
+ config['@updated']({ w: this.node.w, h: this.node.h }, this)
139
134
  }
140
135
 
141
136
  // trigger layout on parent if parent is a layout
@@ -144,33 +139,6 @@ const layoutFn = function (config) {
144
139
  }
145
140
  }
146
141
 
147
- /**
148
- * Checks if a value is a transition object.
149
- * @param {any} value - The value to check.
150
- * @returns {boolean} True if the value is a transition object, false otherwise.
151
- */
152
- const isTransition = (value) => {
153
- return value !== null && typeof value === 'object' && 'transition' in value === true
154
- }
155
-
156
- /**
157
- * Checks if a string is an object string (starts and ends with curly braces).
158
- * @param {string} str - The string to check.
159
- * @returns {boolean} True if the string is an object string, false otherwise.
160
- */
161
- const isObjectString = (str) => {
162
- return typeof str === 'string' && str.startsWith('{') && str.endsWith('}')
163
- }
164
-
165
- /**
166
- * Parses a string into an object, converting single quotes to double and adding quotes to keys.
167
- * @param {string} str - The string to parse.
168
- * @returns {object} The parsed object.
169
- */
170
- const parseToObject = (str) => {
171
- return JSON.parse(str.replace(/'/g, '"').replace(/([{,]\s*)([\w-_]+)(\s*:)/g, '$1"$2"$3'))
172
- }
173
-
174
142
  /**
175
143
  * Parses a percentage string or returns the value as-is.
176
144
  * @param {string|number} v - The value to parse (may be a percentage string).
@@ -242,22 +210,24 @@ const propsTransformer = {
242
210
  this.props['rotation'] = v * (Math.PI / 180)
243
211
  },
244
212
  set w(v) {
245
- this.props['width'] = parsePercentage.call(this, v, 'width')
213
+ if (v < 0) v = 0
214
+ this.props['w'] = parsePercentage.call(this, v, 'w')
246
215
  },
247
216
  set width(v) {
248
- this.props['width'] = parsePercentage.call(this, v, 'width')
217
+ this.w = v
249
218
  },
250
219
  set h(v) {
251
- this.props['height'] = parsePercentage.call(this, v, 'height')
220
+ if (v < 0) v = 0
221
+ this.props['h'] = parsePercentage.call(this, v, 'h')
252
222
  },
253
223
  set height(v) {
254
- this.props['height'] = parsePercentage.call(this, v, 'height')
224
+ this.h = v
255
225
  },
256
226
  set x(v) {
257
- this.props['x'] = parsePercentage.call(this, v, 'width')
227
+ this.props['x'] = parsePercentage.call(this, v, 'w')
258
228
  },
259
229
  set y(v) {
260
- this.props['y'] = parsePercentage.call(this, v, 'height')
230
+ this.props['y'] = parsePercentage.call(this, v, 'h')
261
231
  },
262
232
  set z(v) {
263
233
  this.props['zIndex'] = v
@@ -287,7 +257,7 @@ const propsTransformer = {
287
257
  this.props['color'] = this.props['src'] ? 0xffffffff : 0x00000000
288
258
  }
289
259
  // apply auto sizing when no width or height specified
290
- if (!('w' in this.raw) && !('w' in this.raw) && !('h' in this.raw) && !('height' in this.raw)) {
260
+ if (!('w' in this.raw) && !('h' in this.raw)) {
291
261
  this.props['autosize'] = true
292
262
  }
293
263
  },
@@ -379,37 +349,68 @@ const propsTransformer = {
379
349
  this.props['alpha'] = v
380
350
  }
381
351
  },
352
+ set rounded(v) {
353
+ this.props['rounded'] = v
354
+ if (this.element.node !== undefined && this.elementShader === true) {
355
+ if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
356
+ this.element.node.props['shader'].props = v
357
+ } else {
358
+ if (isArrayString(v) === true) {
359
+ v = JSON.parse(v)
360
+ }
361
+ this.element.node.props['shader'].props.radius = v
362
+ }
363
+ }
364
+ },
365
+ set border(v) {
366
+ this.props['border'] = v
367
+ if (
368
+ this.element.node !== undefined &&
369
+ this.elementShader === true &&
370
+ (typeof v === 'object' || isObjectString(v) === true)
371
+ ) {
372
+ v = shaders.parseProps(v)
373
+ for (const key in v) {
374
+ this.element.node.props['shader'].props[`border-${key}`] = v[key]
375
+ }
376
+ }
377
+ },
378
+ set shadow(v) {
379
+ this.props['shadow'] = v
380
+ if (
381
+ this.element.node !== undefined &&
382
+ this.elementShader === true &&
383
+ (typeof v === 'object' || isObjectString(v) === true)
384
+ ) {
385
+ v = shaders.parseProps(v)
386
+ for (const key in v) {
387
+ this.element.node.props['shader'].props[`shadow-${key}`] = v[key]
388
+ }
389
+ }
390
+ },
382
391
  set shader(v) {
392
+ let type = v
393
+ if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
394
+ type = v.type
395
+ v = shaders.parseProps(v)
396
+ }
383
397
  const target = this.element.node !== undefined ? this.element.node : this.props
384
-
385
- if (v === null) {
386
- target['shader'] = null
398
+ //if v remains a string we can change shader types
399
+ if (typeof v === 'string') {
400
+ target['shader'] = renderer.createShader(type)
387
401
  return
388
402
  }
389
403
 
390
- if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
391
- if (target.shader !== undefined && target.shader.type === v.type) {
392
- for (const prop in v.props) {
393
- target.shader.props[prop] = v.props[prop]
394
- }
404
+ //check again if v is an object since it could have been an object string
405
+ if (typeof v === 'object') {
406
+ if (target.shader !== undefined && type === target.shader.shaderKey) {
407
+ target['shader'].props = v
395
408
  return
396
409
  }
397
- target['shader'] = renderer.createShader(v.type, v.props)
398
- }
399
- },
400
- set effects(v) {
401
- for (let i = 0; i < v.length; i++) {
402
- if (v[i].props && v[i].props.color) {
403
- v[i].props.color = colors.normalize(v[i].props.color)
404
- }
405
- }
406
- if (this.element.node === undefined) {
407
- this.props['shader'] = renderer.createShader('DynamicShader', {
408
- effects: v.map((effect) => {
409
- return renderer.createEffect(effect.type, effect.props)
410
- }),
411
- })
410
+ target['shader'] = renderer.createShader(type, v)
411
+ return
412
412
  }
413
+ target['shader'] = renderer.createShader('DefaultShader')
413
414
  },
414
415
  set clipping(v) {
415
416
  this.props['clipping'] = v
@@ -423,21 +424,27 @@ const propsTransformer = {
423
424
  set size(v) {
424
425
  this.props['fontSize'] = v
425
426
  },
426
- set wordwrap(v) {
427
- Log.warn('The wordwrap attribute is deprecated, use maxwidth instead')
428
- this.props['width'] = v
429
- this.props['contain'] = 'width'
430
- },
431
427
  set maxwidth(v) {
432
- this.props['width'] = v
428
+ this.props['maxWidth'] = v
429
+ if (this.manualTextContain === true) {
430
+ return
431
+ }
432
+ if (this.props['contain'] === 'height') {
433
+ this.props['contain'] = 'both'
434
+ return
435
+ }
433
436
  this.props['contain'] = 'width'
434
437
  },
435
438
  set maxheight(v) {
436
- this.props['height'] = v
437
- this.props['contain'] = 'both'
438
- },
439
- set contain(v) {
440
- this.props['contain'] = v
439
+ this.props['maxHeight'] = v
440
+ if (this.manualTextContain === true) {
441
+ return
442
+ }
443
+ if (this.props['contain'] === 'width') {
444
+ this.props['contain'] = 'both'
445
+ return
446
+ }
447
+ this.props['contain'] = 'height'
441
448
  },
442
449
  set maxlines(v) {
443
450
  this.props['maxLines'] = v
@@ -451,6 +458,10 @@ const propsTransformer = {
451
458
  set lineheight(v) {
452
459
  this.props['lineHeight'] = v
453
460
  },
461
+ set contain(v) {
462
+ this.props['contain'] = v
463
+ this.manualTextContain = true
464
+ },
454
465
  set align(v) {
455
466
  this.props['textAlign'] = v
456
467
  },
@@ -500,13 +511,14 @@ const propsTransformer = {
500
511
  },
501
512
  }
502
513
 
514
+ export const elementAttributes = Object.keys(propsTransformer)
515
+
503
516
  const Element = {
504
517
  /**
505
518
  * Populates the element with data
506
- * @param {import('../../component.js').BlitsElementProps} data
519
+ * @param {import('../../component.js').BlitsElementProps} props
507
520
  */
508
- populate(data) {
509
- const props = data
521
+ populate(props) {
510
522
  props['node'] = this.config.node
511
523
 
512
524
  if (props[symbols.isSlot] === true) {
@@ -519,11 +531,22 @@ const Element = {
519
531
  //@ts-ignore This might be a left over from the old code?
520
532
  delete props.parent
521
533
 
522
- this.props.raw = data
534
+ this.props.raw = props
535
+ this.props.elementShader = false
523
536
 
524
537
  const propKeys = Object.keys(props)
525
538
  const length = propKeys.length
526
539
 
540
+ if (
541
+ props['shader'] === undefined &&
542
+ (props['rounded'] !== undefined ||
543
+ props['border'] !== undefined ||
544
+ props['shadow'] !== undefined)
545
+ ) {
546
+ this.props.elementShader = true
547
+ this.props.props['shader'] = shaders.createElementShader(props)
548
+ }
549
+
527
550
  for (let i = 0; i < length; i++) {
528
551
  const key = propKeys[i]
529
552
  const value = props[key]
@@ -543,7 +566,7 @@ const Element = {
543
566
 
544
567
  if (props['@loaded'] !== undefined && typeof props['@loaded'] === 'function') {
545
568
  this.node.on('loaded', (el, { type, dimensions }) => {
546
- props['@loaded']({ w: dimensions.width, h: dimensions.height, type }, this)
569
+ props['@loaded']({ w: dimensions.w, h: dimensions.h, type }, this)
547
570
  })
548
571
  }
549
572
 
@@ -1,38 +1,33 @@
1
- import { SdfTrFontFace, WebTrFontFace } from '@lightningjs/renderer'
2
1
  import Settings from '../../settings.js'
3
2
  import { renderer } from './launch.js'
4
3
 
4
+ const fontTypeMapping = {
5
+ sdf: 'sdf',
6
+ msdf: 'sdf',
7
+ canvas: 'canvas',
8
+ web: 'canvas',
9
+ }
10
+
5
11
  export default () => {
6
12
  const stage = renderer.stage
7
- Settings.get('fonts', []).forEach((font) => {
8
- if (font.type === 'sdf' || font.type === 'msdf') {
9
- // automatically map png key to file name
10
- if (!font.png && font.file) {
11
- font.png = font.file.replace(/\.[^.]+$/, `.${font.type}.png`)
12
- }
13
- // automatically map json to file name
14
- if (!font.json && font.file) {
15
- font.json = font.file.replace(/\.[^.]+$/, `.${font.type}.json`)
16
- }
17
- stage.fontManager.addFontFace(
18
- new SdfTrFontFace(font.type, {
19
- fontFamily: font.family,
20
- descriptors: {},
21
- atlasUrl: font.png,
22
- atlasDataUrl: font.json,
23
- stage,
24
- metrics: font.metrics,
25
- })
26
- )
27
- } else if (font.type === 'web') {
28
- stage.fontManager.addFontFace(
29
- new WebTrFontFace({
30
- fontFamily: font.family,
31
- fontUrl: font.file,
32
- descriptors: {},
33
- metrics: font.metrics,
34
- })
35
- )
13
+
14
+ const fonts = Settings.get('fonts', [])
15
+ for (let i = 0; i < fonts.length; i++) {
16
+ const font = fonts[i]
17
+ const type = fontTypeMapping[font.type] || 'sdf'
18
+
19
+ if (type === 'sdf') {
20
+ stage.loadFont('sdf', {
21
+ fontFamily: font.family,
22
+ atlasUrl: font.json || (font.file && font.file.replace(/\.[^.]+$/, `.${font.type}.png`)),
23
+ atlasDataUrl:
24
+ font.json || (font.file && font.file.replace(/\.[^.]+$/, `.${font.type}.json`)),
25
+ })
26
+ } else {
27
+ stage.loadFont('canvas', {
28
+ fontFamily: font.family,
29
+ fontUrl: font.file,
30
+ })
36
31
  }
37
- })
32
+ }
38
33
  }
@@ -1,12 +1,62 @@
1
1
  import Settings from '../../settings.js'
2
2
  import { renderer } from './launch.js'
3
+ import * as webglShaders from '@lightningjs/renderer/webgl/shaders'
4
+ import * as canvasShaders from '@lightningjs/renderer/canvas/shaders'
5
+
6
+ function registerBlitsDefaultShaders(
7
+ shManager,
8
+ Rounded,
9
+ Border,
10
+ Shadow,
11
+ RoundedWithBorder,
12
+ RoundedWithShadow,
13
+ RoundedWithBorderAndShadow,
14
+ HolePunch,
15
+ RadialGradient,
16
+ LinearGradient
17
+ ) {
18
+ shManager.registerShaderType('rounded', Rounded)
19
+ shManager.registerShaderType('border', Border)
20
+ shManager.registerShaderType('shadow', Shadow)
21
+ shManager.registerShaderType('roundedWithBorder', RoundedWithBorder)
22
+ shManager.registerShaderType('roundedWithShadow', RoundedWithShadow)
23
+ shManager.registerShaderType('roundedWithBorderAndShadow', RoundedWithBorderAndShadow)
24
+ shManager.registerShaderType('holePunch', HolePunch)
25
+ shManager.registerShaderType('radialGradient', RadialGradient)
26
+ shManager.registerShaderType('linearGradient', LinearGradient)
27
+ }
3
28
 
4
29
  export default () => {
5
30
  const stage = renderer.stage
6
- Settings.get('shaders', []).forEach((shader) => {
7
- stage.shManager.registerShaderType(shader.name, shader.type)
8
- })
9
- Settings.get('effects', []).forEach((effect) => {
10
- stage.shManager.registerShaderType(effect.name, effect.type)
11
- })
31
+
32
+ const {
33
+ Rounded,
34
+ Border,
35
+ Shadow,
36
+ RoundedWithBorder,
37
+ RoundedWithShadow,
38
+ RoundedWithBorderAndShadow,
39
+ HolePunch,
40
+ RadialGradient,
41
+ LinearGradient,
42
+ } = Settings.get('renderMode', 'webgl') === 'webgl' ? webglShaders : canvasShaders
43
+
44
+ registerBlitsDefaultShaders(
45
+ stage.shManager,
46
+ Rounded,
47
+ Border,
48
+ Shadow,
49
+ RoundedWithBorder,
50
+ RoundedWithShadow,
51
+ RoundedWithBorderAndShadow,
52
+ HolePunch,
53
+ RadialGradient,
54
+ LinearGradient
55
+ )
56
+
57
+ const shaders = Settings.get('shaders', [])
58
+ const len = shaders.length
59
+ for (let i = 0; i < len; i++) {
60
+ stage.shManager.registerShaderType(shaders[i].name, shaders[i].type)
61
+ }
12
62
  }
package/src/focus.js CHANGED
@@ -50,7 +50,7 @@ export default {
50
50
 
51
51
  // unfocus currently focused components
52
52
  if (focusedComponent !== null) {
53
- if (focusChain[focusChain.length - 1] === component.parent) {
53
+ if (focusChain[focusChain.length - 1] === component[symbols.parent]) {
54
54
  focusChain.push(component)
55
55
  } else {
56
56
  const newFocusChain = getAncestors([component])
@@ -58,7 +58,7 @@ export default {
58
58
  while (i--) {
59
59
  // don't unfocus when part of the new focus chain
60
60
  if (newFocusChain.indexOf(focusChain[i]) > -1) break
61
- focusChain[i].lifecycle.state = 'unfocus'
61
+ focusChain[i][symbols.lifecycle].state = 'unfocus'
62
62
  }
63
63
  focusChain = newFocusChain
64
64
  }
@@ -67,7 +67,7 @@ export default {
67
67
  // ensure that all components in the focus path have focus state
68
68
  let i = 0
69
69
  while (i < focusChain.length - 1) {
70
- focusChain[i].lifecycle.state = 'focus'
70
+ focusChain[i][symbols.lifecycle].state = 'focus'
71
71
  i++
72
72
  }
73
73
 
@@ -105,8 +105,8 @@ export default {
105
105
  * @returns array components
106
106
  */
107
107
  const getAncestors = (components) => {
108
- if (components[0].parent !== undefined) {
109
- components.unshift(components[0].parent)
108
+ if (components[0][symbols.parent] !== undefined) {
109
+ components.unshift(components[0][symbols.parent])
110
110
  return getAncestors(components)
111
111
  }
112
112
  return components
@@ -125,8 +125,8 @@ export const getComponentWithInputEvent = (component, key) => {
125
125
  typeof component[symbols.inputEvents].any === 'function')
126
126
  ) {
127
127
  return component
128
- } else if (component.parent !== undefined) {
129
- return getComponentWithInputEvent(component.parent, key)
128
+ } else if (component[symbols.parent] !== undefined) {
129
+ return getComponentWithInputEvent(component[symbols.parent], key)
130
130
  } else return null
131
131
  }
132
132
 
@@ -138,11 +138,11 @@ export const getComponentWithInputEvent = (component, key) => {
138
138
  const setFocus = (component, event) => {
139
139
  Log.info(
140
140
  '\nFocus chain:\n',
141
- focusChain.map((c, index) => '\t'.repeat(index) + '↳ ' + c.componentId).join('\n')
141
+ focusChain.map((c, index) => '\t'.repeat(index) + '↳ ' + c.$componentId).join('\n')
142
142
  )
143
143
 
144
144
  focusedComponent = component
145
- component.lifecycle.state = 'focus'
145
+ component[symbols.lifecycle].state = 'focus'
146
146
 
147
147
  if (event instanceof KeyboardEvent) {
148
148
  const internalEvent = new KeyboardEvent('keydown', event)
package/src/launch.js CHANGED
@@ -41,9 +41,8 @@ import blitsPackageInfo from '../package.json' with { type: 'json' }
41
41
 
42
42
  /**
43
43
  * @typedef {import('@lightningjs/renderer').RendererMain} RendererMain
44
- * @type {RendererMain}
44
+ * @type {RendererMain | {}}
45
45
  */
46
- // @ts-ignore - We ignore this because it will be replaced by the renderer once the app is launched
47
46
  export let renderer = {}
48
47
  export const stage = {}
49
48