@lightningjs/blits
Advanced tools
Comparing version 1.14.1 to 1.15.0
# Changelog | ||
## v1.15.0 | ||
_14 jan 2025_ | ||
- Added `placement`-attribute for easily aligning Elements to predefined locations (i.e. `center`, `right`, `middle`, `bottom`) | ||
- Removed automatic injection of `index` variable into forloop-scope to prevent unexpected naming collisions | ||
## v1.14.1 | ||
@@ -4,0 +12,0 @@ |
@@ -39,2 +39,34 @@ # Supported Element attributes | ||
### Predefined placement options | ||
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. | ||
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`. | ||
The _placement_ attribute also accepts and object with an `x` and a `y` key, to specify a placement for both axes. | ||
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). | ||
```xml | ||
<Element w="300" h="300"> | ||
<!-- x placement --> | ||
<Element w="40" h="40" placement="left" color="#818cf8" /> | ||
<Element w="40" h="40" placement="center" color="#2563eb" /> | ||
<Element w="40" h="40" placement="right" color="#1e40af" /> | ||
<!-- y placement --> | ||
<Element w="40" h="40" x="54" placement="top" color="#f472b6" /> | ||
<Element w="40" h="40" x="54" placement="middle" color="#db2777" /> | ||
<Element w="40" h="40" x="54" placement="bottom" color="#be185d" /> | ||
<!-- x/y placement --> | ||
<Element w="40" h="40" placement="{x: 'center', y: 'bottom'}" color="#a3e635" /> | ||
<Element w="40" h="40" placement="{x: 'right', y: 'middle'}" color="#65a30d" /> | ||
<Element w="40" h="40" placement="{x: 'center', y: 'middle'}" color="#4d7c0f" /> | ||
</Element> | ||
``` | ||
> note: the `x` or `y` attributes on the Element are ignored for those axes defined in the `placement`-attribute | ||
## Colors | ||
@@ -41,0 +73,0 @@ |
{ | ||
"name": "@lightningjs/blits", | ||
"version": "1.14.1", | ||
"version": "1.15.0", | ||
"description": "Blits: The Lightning 3 App Development Framework", | ||
@@ -5,0 +5,0 @@ "bin": "bin/index.js", |
@@ -386,2 +386,33 @@ /* | ||
}, | ||
set placement(v) { | ||
let x, y | ||
if (typeof v === 'object' || (isObjectString(v) === true && (v = parseToObject(v)))) { | ||
if ('x' in v === true) { | ||
x = v.x | ||
} | ||
if ('y' in v === true) { | ||
y = v.y | ||
} | ||
} else { | ||
v === 'center' || v === 'right' ? (x = v) : (y = v) | ||
} | ||
// Set X position | ||
if (x === 'center') { | ||
this.x = '50%' | ||
this.props['mountX'] = 0.5 | ||
} else if (x === 'right') { | ||
this.x = '100%' | ||
this.props['mountX'] = 1 | ||
} | ||
// Set Y position | ||
if (y === 'middle') { | ||
this.y = '50%' | ||
this.props['mountY'] = 0.5 | ||
} else if (y === 'bottom') { | ||
this.y = '100%' | ||
this.props['mountY'] = 1 | ||
} | ||
}, | ||
} | ||
@@ -388,0 +419,0 @@ |
@@ -365,7 +365,7 @@ /* | ||
test('Element - Set `float` property with value `center`', (assert) => { | ||
test('Element - Set `placement` property with value `center`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('float', 'center') | ||
el.set('placement', 'center') | ||
@@ -376,2 +376,7 @@ assert.equal(el.node['mountX'], 0.5, 'Node mountX parameter should set to 0.5') | ||
assert.equal(el.props.props['x'], 960, 'props x parameter should be set to 960') | ||
assert.equal( | ||
el.node['y'], | ||
undefined, | ||
'Node Y parameter should not be modified from default value' | ||
) | ||
@@ -381,7 +386,7 @@ assert.end() | ||
test('Element - Set `float` property with value `right`', (assert) => { | ||
test('Element - Set `placement` property with value `right`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('float', 'right') | ||
el.set('placement', 'right') | ||
@@ -392,2 +397,7 @@ assert.equal(el.node['mountX'], 1, 'Node mountX parameter should set to 1') | ||
assert.equal(el.props.props['x'], 1920, 'props x parameter should be set to 1920') | ||
assert.equal( | ||
el.node['y'], | ||
undefined, | ||
'Node Y parameter should not be modified from default value' | ||
) | ||
@@ -397,2 +407,126 @@ assert.end() | ||
test('Element - Set `placement` property with value `middle`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', 'middle') | ||
assert.equal(el.node['mountY'], 0.5, 'Node mountY parameter should set to 0.5') | ||
assert.equal(el.props.props['mountY'], 0.5, 'Props mountY parameter should set to 0.5') | ||
assert.equal(el.node['y'], 540, 'Node Y parameter should set to half of parent node height, 540') | ||
assert.equal(el.props.props['y'], 540, 'props Y parameter should be set to 540') | ||
assert.equal( | ||
el.node['x'], | ||
undefined, | ||
'Node X parameter should not be modified from default value' | ||
) | ||
assert.end() | ||
}) | ||
test('Element - Set `placement` property with value `bottom`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', 'bottom') | ||
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1') | ||
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1') | ||
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node full height, 1080') | ||
assert.equal(el.props.props['y'], 1080, 'props Y parameter should be set to 1080') | ||
assert.equal( | ||
el.node['x'], | ||
undefined, | ||
'Node X parameter should not be modified from default value' | ||
) | ||
assert.end() | ||
}) | ||
test('Element - Set `placement` property with value `bottom` & x = 300', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', 'bottom') | ||
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1') | ||
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1') | ||
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node full height, 1080') | ||
assert.equal(el.props.props['y'], 1080, 'props Y parameter should be set to 1080') | ||
el.set('x', 300) | ||
assert.equal(el.node['x'], 300, 'Node x parameter should set custom value 300') | ||
assert.end() | ||
}) | ||
test('Element - Set `placement` property with object value `{x:"center", y:"middle"}`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', "{x:'center', y:'middle'}") | ||
assert.equal(el.node['mountX'], 0.5, 'Node mountX parameter should set to 0.5') | ||
assert.equal(el.props.props['mountX'], 0.5, 'Props mountX parameter should set to 0.5') | ||
assert.equal(el.node['x'], 960, 'Node x parameter should set to half of parent node width, 960') | ||
assert.equal(el.node['mountY'], 0.5, 'Node mountY parameter should set to 0.5') | ||
assert.equal(el.props.props['mountY'], 0.5, 'Props mountY parameter should set to 0.5') | ||
assert.equal(el.node['y'], 540, 'Node Y parameter should set to half of parent node height, 540') | ||
assert.end() | ||
}) | ||
test('Element - Set `placement` property with object value `{x:"center", y:"bottom"}`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', "{x:'center', y:'bottom'}") | ||
assert.equal(el.node['mountX'], 0.5, 'Node mountX parameter should set to 0.5') | ||
assert.equal(el.props.props['mountX'], 0.5, 'Props mountX parameter should set to 0.5') | ||
assert.equal(el.node['x'], 960, 'Node x parameter should set to half of parent node width, 960') | ||
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1') | ||
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1') | ||
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node full height , 1080') | ||
assert.end() | ||
}) | ||
test('Element - Set `placement` property with object value `{x:"right", y:"middle"}`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', "{x:'right', y:'middle'}") | ||
assert.equal(el.node['mountX'], 1, 'Node mountX parameter should set to 1') | ||
assert.equal(el.props.props['mountX'], 1, 'Props mountX parameter should set to 1') | ||
assert.equal(el.node['x'], 1920, 'Node x parameter should set to parent node full width, 1920') | ||
assert.equal(el.node['mountY'], 0.5, 'Node mountY parameter should set to 0.5') | ||
assert.equal(el.props.props['mountY'], 0.5, 'Props mountY parameter should set to 0.5') | ||
assert.equal(el.node['y'], 540, 'Node Y parameter should set to half of parent node height, 540') | ||
assert.end() | ||
}) | ||
test('Element - Set `placement` property with object value `{x:"right", y:"bottom"}`', (assert) => { | ||
assert.capture(renderer, 'createNode', () => new EventEmitter()) | ||
const el = createElement() | ||
el.set('placement', "{x:'right', y:'bottom'}") | ||
assert.equal(el.node['mountX'], 1, 'Node mountX parameter should set to 1') | ||
assert.equal(el.props.props['mountX'], 1, 'Props mountX parameter should set to 1') | ||
assert.equal(el.node['x'], 1920, 'Node x parameter should set to parent node full width, 1920') | ||
assert.equal(el.node['mountY'], 1, 'Node mountY parameter should set to 1') | ||
assert.equal(el.props.props['mountY'], 1, 'Props mountY parameter should set to 1') | ||
assert.equal(el.node['y'], 1080, 'Node Y parameter should set to parent node height, 1080') | ||
assert.end() | ||
}) | ||
test('Element - Set `float` property with value `unknown`', (assert) => { | ||
@@ -399,0 +533,0 @@ assert.capture(renderer, 'createNode', () => new EventEmitter()) |
@@ -291,3 +291,3 @@ /* | ||
// can be improved with a smarter regex | ||
const [item, index = 'index'] = result[1] | ||
const [item, index] = result[1] | ||
.replace('(', '') | ||
@@ -310,8 +310,11 @@ .replace(')', '') | ||
const indexRegex = new RegExp(`\\$${index}(?!['\\w])`) | ||
const indexResult = indexRegex.exec(key) | ||
if (Array.isArray(indexResult)) { | ||
ctx.renderCode.push( | ||
`console.warn(" Using '${index}' in the key, like key=${key}, is not recommended")` | ||
) | ||
// If the index variable is not defined, the key attribute would not reference it. | ||
if (index !== undefined) { | ||
const indexRegex = new RegExp(`\\$${index}(?!['\\w])`) | ||
const indexResult = indexRegex.exec(key) | ||
if (Array.isArray(indexResult)) { | ||
ctx.renderCode.push( | ||
`console.warn(" Using '${index}' in the key, like key=${key}, is not recommended")` | ||
) | ||
} | ||
} | ||
@@ -329,3 +332,10 @@ | ||
const ${item} = rawCollection[l] | ||
`) | ||
// push reference of index variable | ||
if (index !== undefined) { | ||
ctx.renderCode.push(` | ||
const ${index} = l | ||
`) | ||
} | ||
ctx.renderCode.push(` | ||
keys.add('' + ${interpolate(key, '') || 'l'}) | ||
@@ -347,4 +357,11 @@ } | ||
parent = ${parent} | ||
scope['${item}'] = rawCollection[__index] | ||
`) | ||
// If the index variable is declared, include it in the scope object | ||
if (index !== '') { | ||
ctx.renderCode.push(` | ||
scope['${index}'] = __index | ||
scope['${item}'] = rawCollection[__index] | ||
`) | ||
} | ||
ctx.renderCode.push(` | ||
scope['key'] = '' + ${forKey || '__index'} | ||
@@ -351,0 +368,0 @@ `) |
651542
13409