@lightningjs/blits 1.14.1 → 1.15.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,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v1.15.0
|
|
4
|
+
|
|
5
|
+
_14 jan 2025_
|
|
6
|
+
|
|
7
|
+
- Added `placement`-attribute for easily aligning Elements to predefined locations (i.e. `center`, `right`, `middle`, `bottom`)
|
|
8
|
+
- Removed automatic injection of `index` variable into forloop-scope to prevent unexpected naming collisions
|
|
9
|
+
|
|
10
|
+
|
|
3
11
|
## v1.14.1
|
|
4
12
|
|
|
5
13
|
_8 jan 2025_
|
|
@@ -36,6 +36,38 @@ Besides using values in pixels (i.e. `w="100" h="300"`), you can also specify _p
|
|
|
36
36
|
The percentage value specified for `w` and `x` will be calculated as the percentage of the _width_ (`w`) of the parent element.
|
|
37
37
|
And the percentage specified for `h` and `y` will use the _height_ (`h`) of the parent element as the base of the percentage calculation.
|
|
38
38
|
|
|
39
|
+
### Predefined placement options
|
|
40
|
+
|
|
41
|
+
In addition to the absolute positions that Blits and Lightning use, there are a few predefined placement options available. By adding the `placement`-attribute to an Element we can easily align it to the _center_, _left_, _right_, _top_, _bottom_, or even a combination like `{y: 'middle', x: 'left'}`, without having to calculate the positions yourself.
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
On the `x`-axis the following _placement_ options can be used: `left` (default), `center` and `right`. On the `y`-axis the _placement_ attribute accepts `top` (default), `middle` and `bottom`.
|
|
45
|
+
|
|
46
|
+
The _placement_ attribute also accepts and object with an `x` and a `y` key, to specify a placement for both axes.
|
|
47
|
+
|
|
48
|
+
The placement of an Element is calculated based on the dimensions of it's direct parent. This means that the containing Element _must_ have it's own dimensions (i.e. a `w` and a `h` attribute).
|
|
49
|
+
|
|
50
|
+
```xml
|
|
51
|
+
<Element w="300" h="300">
|
|
52
|
+
<!-- x placement -->
|
|
53
|
+
<Element w="40" h="40" placement="left" color="#818cf8" />
|
|
54
|
+
<Element w="40" h="40" placement="center" color="#2563eb" />
|
|
55
|
+
<Element w="40" h="40" placement="right" color="#1e40af" />
|
|
56
|
+
|
|
57
|
+
<!-- y placement -->
|
|
58
|
+
<Element w="40" h="40" x="54" placement="top" color="#f472b6" />
|
|
59
|
+
<Element w="40" h="40" x="54" placement="middle" color="#db2777" />
|
|
60
|
+
<Element w="40" h="40" x="54" placement="bottom" color="#be185d" />
|
|
61
|
+
|
|
62
|
+
<!-- x/y placement -->
|
|
63
|
+
<Element w="40" h="40" placement="{x: 'center', y: 'bottom'}" color="#a3e635" />
|
|
64
|
+
<Element w="40" h="40" placement="{x: 'right', y: 'middle'}" color="#65a30d" />
|
|
65
|
+
<Element w="40" h="40" placement="{x: 'center', y: 'middle'}" color="#4d7c0f" />
|
|
66
|
+
</Element>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
> note: the `x` or `y` attributes on the Element are ignored for those axes defined in the `placement`-attribute
|
|
70
|
+
|
|
39
71
|
## Colors
|
|
40
72
|
|
|
41
73
|
By default, Elements have a transparent background color. The `color` attribute can be used to give an Element a color.
|
package/package.json
CHANGED
|
@@ -383,6 +383,37 @@ const propsTransformer = {
|
|
|
383
383
|
set content(v) {
|
|
384
384
|
this.props['text'] = '' + v
|
|
385
385
|
},
|
|
386
|
+
set placement(v) {
|
|
387
|
+
let x, y
|
|
388
|
+
if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) {
|
|
389
|
+
if ('x' in v === true) {
|
|
390
|
+
x = v.x
|
|
391
|
+
}
|
|
392
|
+
if ('y' in v === true) {
|
|
393
|
+
y = v.y
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
v === 'center' || v === 'right' ? (x = v) : (y = v)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Set X position
|
|
400
|
+
if (x === 'center') {
|
|
401
|
+
this.x = '50%'
|
|
402
|
+
this.props['mountX'] = 0.5
|
|
403
|
+
} else if (x === 'right') {
|
|
404
|
+
this.x = '100%'
|
|
405
|
+
this.props['mountX'] = 1
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Set Y position
|
|
409
|
+
if (y === 'middle') {
|
|
410
|
+
this.y = '50%'
|
|
411
|
+
this.props['mountY'] = 0.5
|
|
412
|
+
} else if (y === 'bottom') {
|
|
413
|
+
this.y = '100%'
|
|
414
|
+
this.props['mountY'] = 1
|
|
415
|
+
}
|
|
416
|
+
},
|
|
386
417
|
}
|
|
387
418
|
|
|
388
419
|
const Element = {
|
|
@@ -362,30 +362,164 @@ test('Element - Set `fit` property should not set not required keys', (assert) =
|
|
|
362
362
|
assert.end()
|
|
363
363
|
})
|
|
364
364
|
|
|
365
|
-
test('Element - Set `
|
|
365
|
+
test('Element - Set `placement` property with value `center`', (assert) => {
|
|
366
366
|
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
367
367
|
const el = createElement()
|
|
368
368
|
|
|
369
|
-
el.set('
|
|
369
|
+
el.set('placement', 'center')
|
|
370
370
|
|
|
371
371
|
assert.equal(el.node['mountX'], 0.5, 'Node mountX parameter should set to 0.5')
|
|
372
372
|
assert.equal(el.props.props['mountX'], 0.5, 'Props mountX parameter should set to 0.5')
|
|
373
373
|
assert.equal(el.node['x'], 960, 'Node x parameter should set to half of parent node width, 960')
|
|
374
374
|
assert.equal(el.props.props['x'], 960, 'props x parameter should be set to 960')
|
|
375
|
+
assert.equal(
|
|
376
|
+
el.node['y'],
|
|
377
|
+
undefined,
|
|
378
|
+
'Node Y parameter should not be modified from default value'
|
|
379
|
+
)
|
|
375
380
|
|
|
376
381
|
assert.end()
|
|
377
382
|
})
|
|
378
383
|
|
|
379
|
-
test('Element - Set `
|
|
384
|
+
test('Element - Set `placement` property with value `right`', (assert) => {
|
|
380
385
|
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
381
386
|
const el = createElement()
|
|
382
387
|
|
|
383
|
-
el.set('
|
|
388
|
+
el.set('placement', 'right')
|
|
384
389
|
|
|
385
390
|
assert.equal(el.node['mountX'], 1, 'Node mountX parameter should set to 1')
|
|
386
391
|
assert.equal(el.props.props['mountX'], 1, 'Props mountX parameter should set to 1')
|
|
387
392
|
assert.equal(el.node['x'], 1920, 'Node x parameter should set to parent node full width, 1920')
|
|
388
393
|
assert.equal(el.props.props['x'], 1920, 'props x parameter should be set to 1920')
|
|
394
|
+
assert.equal(
|
|
395
|
+
el.node['y'],
|
|
396
|
+
undefined,
|
|
397
|
+
'Node Y parameter should not be modified from default value'
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
assert.end()
|
|
401
|
+
})
|
|
402
|
+
|
|
403
|
+
test('Element - Set `placement` property with value `middle`', (assert) => {
|
|
404
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
405
|
+
const el = createElement()
|
|
406
|
+
|
|
407
|
+
el.set('placement', 'middle')
|
|
408
|
+
|
|
409
|
+
assert.equal(el.node['mountY'], 0.5, 'Node mountY parameter should set to 0.5')
|
|
410
|
+
assert.equal(el.props.props['mountY'], 0.5, 'Props mountY parameter should set to 0.5')
|
|
411
|
+
assert.equal(el.node['y'], 540, 'Node Y parameter should set to half of parent node height, 540')
|
|
412
|
+
assert.equal(el.props.props['y'], 540, 'props Y parameter should be set to 540')
|
|
413
|
+
assert.equal(
|
|
414
|
+
el.node['x'],
|
|
415
|
+
undefined,
|
|
416
|
+
'Node X parameter should not be modified from default value'
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
assert.end()
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
test('Element - Set `placement` property with value `bottom`', (assert) => {
|
|
423
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
424
|
+
const el = createElement()
|
|
425
|
+
|
|
426
|
+
el.set('placement', 'bottom')
|
|
427
|
+
|
|
428
|
+
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1')
|
|
429
|
+
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1')
|
|
430
|
+
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node full height, 1080')
|
|
431
|
+
assert.equal(el.props.props['y'], 1080, 'props Y parameter should be set to 1080')
|
|
432
|
+
assert.equal(
|
|
433
|
+
el.node['x'],
|
|
434
|
+
undefined,
|
|
435
|
+
'Node X parameter should not be modified from default value'
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
assert.end()
|
|
439
|
+
})
|
|
440
|
+
|
|
441
|
+
test('Element - Set `placement` property with value `bottom` & x = 300', (assert) => {
|
|
442
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
443
|
+
const el = createElement()
|
|
444
|
+
|
|
445
|
+
el.set('placement', 'bottom')
|
|
446
|
+
|
|
447
|
+
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1')
|
|
448
|
+
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1')
|
|
449
|
+
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node full height, 1080')
|
|
450
|
+
assert.equal(el.props.props['y'], 1080, 'props Y parameter should be set to 1080')
|
|
451
|
+
|
|
452
|
+
el.set('x', 300)
|
|
453
|
+
|
|
454
|
+
assert.equal(el.node['x'], 300, 'Node x parameter should set custom value 300')
|
|
455
|
+
|
|
456
|
+
assert.end()
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
test('Element - Set `placement` property with object value `{x:"center", y:"middle"}`', (assert) => {
|
|
460
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
461
|
+
const el = createElement()
|
|
462
|
+
|
|
463
|
+
el.set('placement', "{x:'center', y:'middle'}")
|
|
464
|
+
|
|
465
|
+
assert.equal(el.node['mountX'], 0.5, 'Node mountX parameter should set to 0.5')
|
|
466
|
+
assert.equal(el.props.props['mountX'], 0.5, 'Props mountX parameter should set to 0.5')
|
|
467
|
+
assert.equal(el.node['x'], 960, 'Node x parameter should set to half of parent node width, 960')
|
|
468
|
+
|
|
469
|
+
assert.equal(el.node['mountY'], 0.5, 'Node mountY parameter should set to 0.5')
|
|
470
|
+
assert.equal(el.props.props['mountY'], 0.5, 'Props mountY parameter should set to 0.5')
|
|
471
|
+
assert.equal(el.node['y'], 540, 'Node Y parameter should set to half of parent node height, 540')
|
|
472
|
+
|
|
473
|
+
assert.end()
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
test('Element - Set `placement` property with object value `{x:"center", y:"bottom"}`', (assert) => {
|
|
477
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
478
|
+
const el = createElement()
|
|
479
|
+
|
|
480
|
+
el.set('placement', "{x:'center', y:'bottom'}")
|
|
481
|
+
|
|
482
|
+
assert.equal(el.node['mountX'], 0.5, 'Node mountX parameter should set to 0.5')
|
|
483
|
+
assert.equal(el.props.props['mountX'], 0.5, 'Props mountX parameter should set to 0.5')
|
|
484
|
+
assert.equal(el.node['x'], 960, 'Node x parameter should set to half of parent node width, 960')
|
|
485
|
+
|
|
486
|
+
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1')
|
|
487
|
+
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1')
|
|
488
|
+
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node full height , 1080')
|
|
489
|
+
|
|
490
|
+
assert.end()
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
test('Element - Set `placement` property with object value `{x:"right", y:"middle"}`', (assert) => {
|
|
494
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
495
|
+
const el = createElement()
|
|
496
|
+
|
|
497
|
+
el.set('placement', "{x:'right', y:'middle'}")
|
|
498
|
+
|
|
499
|
+
assert.equal(el.node['mountX'], 1, 'Node mountX parameter should set to 1')
|
|
500
|
+
assert.equal(el.props.props['mountX'], 1, 'Props mountX parameter should set to 1')
|
|
501
|
+
assert.equal(el.node['x'], 1920, 'Node x parameter should set to parent node full width, 1920')
|
|
502
|
+
|
|
503
|
+
assert.equal(el.node['mountY'], 0.5, 'Node mountY parameter should set to 0.5')
|
|
504
|
+
assert.equal(el.props.props['mountY'], 0.5, 'Props mountY parameter should set to 0.5')
|
|
505
|
+
assert.equal(el.node['y'], 540, 'Node Y parameter should set to half of parent node height, 540')
|
|
506
|
+
|
|
507
|
+
assert.end()
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
test('Element - Set `placement` property with object value `{x:"right", y:"bottom"}`', (assert) => {
|
|
511
|
+
assert.capture(renderer, 'createNode', () => new EventEmitter())
|
|
512
|
+
const el = createElement()
|
|
513
|
+
|
|
514
|
+
el.set('placement', "{x:'right', y:'bottom'}")
|
|
515
|
+
|
|
516
|
+
assert.equal(el.node['mountX'], 1, 'Node mountX parameter should set to 1')
|
|
517
|
+
assert.equal(el.props.props['mountX'], 1, 'Props mountX parameter should set to 1')
|
|
518
|
+
assert.equal(el.node['x'], 1920, 'Node x parameter should set to parent node full width, 1920')
|
|
519
|
+
|
|
520
|
+
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1')
|
|
521
|
+
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1')
|
|
522
|
+
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node height, 1080')
|
|
389
523
|
|
|
390
524
|
assert.end()
|
|
391
525
|
})
|
|
@@ -288,7 +288,7 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
288
288
|
const result = regex.exec(forLoop)
|
|
289
289
|
|
|
290
290
|
// can be improved with a smarter regex
|
|
291
|
-
const [item, index
|
|
291
|
+
const [item, index] = result[1]
|
|
292
292
|
.replace('(', '')
|
|
293
293
|
.replace(')', '')
|
|
294
294
|
.split(/\s*,\s*/)
|
|
@@ -306,12 +306,15 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
306
306
|
ctx.renderCode.push(`parent = ${parent}`)
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
309
|
+
// If the index variable is not defined, the key attribute would not reference it.
|
|
310
|
+
if (index !== undefined) {
|
|
311
|
+
const indexRegex = new RegExp(`\\$${index}(?!['\\w])`)
|
|
312
|
+
const indexResult = indexRegex.exec(key)
|
|
313
|
+
if (Array.isArray(indexResult)) {
|
|
314
|
+
ctx.renderCode.push(
|
|
315
|
+
`console.warn(" Using '${index}' in the key, like key=${key}, is not recommended")`
|
|
316
|
+
)
|
|
317
|
+
}
|
|
315
318
|
}
|
|
316
319
|
|
|
317
320
|
const forStartCounter = counter
|
|
@@ -324,7 +327,14 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
324
327
|
let l = rawCollection.length
|
|
325
328
|
while(l--) {
|
|
326
329
|
const ${item} = rawCollection[l]
|
|
330
|
+
`)
|
|
331
|
+
// push reference of index variable
|
|
332
|
+
if (index !== undefined) {
|
|
333
|
+
ctx.renderCode.push(`
|
|
327
334
|
const ${index} = l
|
|
335
|
+
`)
|
|
336
|
+
}
|
|
337
|
+
ctx.renderCode.push(`
|
|
328
338
|
keys.add('' + ${interpolate(key, '') || 'l'})
|
|
329
339
|
}
|
|
330
340
|
`)
|
|
@@ -341,8 +351,15 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
341
351
|
for(let __index = 0; __index < length; __index++) {
|
|
342
352
|
const scope = Object.create(component)
|
|
343
353
|
parent = ${parent}
|
|
344
|
-
scope['${index}'] = __index
|
|
345
354
|
scope['${item}'] = rawCollection[__index]
|
|
355
|
+
`)
|
|
356
|
+
// If the index variable is declared, include it in the scope object
|
|
357
|
+
if (index !== '') {
|
|
358
|
+
ctx.renderCode.push(`
|
|
359
|
+
scope['${index}'] = __index
|
|
360
|
+
`)
|
|
361
|
+
}
|
|
362
|
+
ctx.renderCode.push(`
|
|
346
363
|
scope['key'] = '' + ${forKey || '__index'}
|
|
347
364
|
`)
|
|
348
365
|
if ('ref' in templateObject && templateObject.ref.indexOf('$') === -1) {
|