@lightningjs/blits 0.4.2 → 0.5.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ # v0.5.1
4
+
5
+ _29 nov 2023_
6
+
7
+ - Fixed issue with unexpected unfocus
8
+ - Added fastforward of transitions on the same property
9
+ - Added functionality to skip focus change on key hold
10
+
11
+ # v0.5.0
12
+
13
+ _23 nov 2023_
14
+
15
+ - Introduced `wordwrap` and `maxlines` attributes on the Text-component, replacing the previous `w` and `h` attributes (breaking change!)
16
+
3
17
  # v0.4.2
4
18
 
5
19
  _22 nov 2023_
@@ -31,6 +31,6 @@
31
31
  "vite": "^4.0.4"
32
32
  },
33
33
  "dependencies": {
34
- "@lightningjs/blits": "^0.4.2"
34
+ "@lightningjs/blits": "^0.5.1"
35
35
  }
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "0.4.2",
3
+ "version": "0.5.1",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.cjs",
6
6
  "exports": {
@@ -43,21 +43,34 @@ const Application = (config) => {
43
43
 
44
44
  config.hooks = config.hooks || {}
45
45
 
46
- let handler
46
+ let keyDownHandler
47
+ let keyUpHandler
48
+ let holdTimeout
47
49
 
48
50
  config.hooks[symbols.destroy] = function () {
49
- document.removeEventListener('keydown', handler)
51
+ document.removeEventListener('keydown', keyDownHandler)
52
+ document.removeEventListener('keyup', keyUpHandler)
50
53
  }
51
54
 
52
55
  config.hooks[symbols.init] = function () {
53
56
  const keyMap = { ...defaultKeyMap, ...Settings.get('keymap', {}) }
54
57
 
55
- handler = (e) => {
58
+ keyDownHandler = (e) => {
56
59
  const key = keyMap[e.key] || keyMap[e.keyCode] || e.key || e.keyCode
57
60
  Focus.input(key, e)
61
+ clearTimeout(holdTimeout)
62
+ holdTimeout = setTimeout(() => {
63
+ Focus.hold = true
64
+ }, 50)
58
65
  }
59
66
 
60
- document.addEventListener('keydown', handler)
67
+ keyUpHandler = () => {
68
+ clearTimeout(holdTimeout)
69
+ Focus.hold = false
70
+ }
71
+
72
+ document.addEventListener('keydown', keyDownHandler)
73
+ document.addEventListener('keyup', keyUpHandler)
61
74
 
62
75
  // next tick
63
76
  setTimeout(() => Focus.set(this))
@@ -31,8 +31,8 @@ export default () =>
31
31
  letterSpacing="$letterspacing"
32
32
  stretch="$stretch"
33
33
  contain="$_contain"
34
- :w="$w"
35
- :h="$h"
34
+ :wordWrap="$wordwrap"
35
+ :maxLines="$maxlines"
36
36
  :textAlign="$align"
37
37
  @loaded="$@loaded"
38
38
  @error="$@error"
@@ -54,15 +54,18 @@ export default () =>
54
54
  'letterspacing',
55
55
  'stretch',
56
56
  'align',
57
- 'w',
58
- 'h',
57
+ 'wordwrap',
58
+ 'maxlines',
59
59
  'contain',
60
60
  '@loaded',
61
61
  '@error',
62
62
  ],
63
63
  computed: {
64
64
  _contain() {
65
- return this.contain || (this.w && this.h ? 'both' : this.w ? 'width' : 'none')
65
+ return (
66
+ this.contain ||
67
+ (this.wordwrap && this.maxlines ? 'both' : this.wordwrap ? 'width' : 'none')
68
+ )
66
69
  },
67
70
  },
68
71
  })
package/src/element.js CHANGED
@@ -54,6 +54,8 @@ const transformations = {
54
54
  delete props.h
55
55
  'z' in props && (props.zIndex = props.z)
56
56
  delete props.z
57
+ 'wordWrap' in props && (props.width = props.wordWrap)
58
+ delete props.wordWrap
57
59
  },
58
60
  parent(props) {
59
61
  if (props.parent === 'root') {
@@ -161,6 +163,12 @@ const transformations = {
161
163
  texture(props, setProperties) {
162
164
  this.src(props, setProperties)
163
165
  },
166
+ maxLines(props, setProperties, element) {
167
+ if (props.maxLines) {
168
+ props.height = props.maxLines * element.node.fontSize
169
+ }
170
+ delete props.maxLines
171
+ },
164
172
  }
165
173
 
166
174
  const Element = {
@@ -217,7 +225,7 @@ const Element = {
217
225
 
218
226
  transformations.remap(props)
219
227
  if (transformations[prop]) {
220
- transformations[prop](props, this.setProperties)
228
+ transformations[prop](props, this.setProperties, this)
221
229
  }
222
230
 
223
231
  Object.keys(props).forEach((prop) => {
@@ -240,6 +248,15 @@ const Element = {
240
248
  return this.initData.ref || null
241
249
  },
242
250
  animate(prop, value) {
251
+ if (this.scheduledTransitions[prop]) {
252
+ clearTimeout(this.scheduledTransitions[prop].timeout)
253
+ if (this.scheduledTransitions[prop].f.state === 'running') {
254
+ this.scheduledTransitions[prop].f.pause()
255
+ // fastforward to final value
256
+ this.node[prop] = this.scheduledTransitions[prop].v
257
+ }
258
+ }
259
+
243
260
  const props = {}
244
261
  props[prop] = transformations.unpackTransition(value)
245
262
 
@@ -263,9 +280,16 @@ const Element = {
263
280
  typeof value === 'object' ? ('function' in value ? value.function : 'ease') : 'ease',
264
281
  })
265
282
  return new Promise((resolve) => {
266
- value.delay
267
- ? setTimeout(() => f.start().waitUntilStopped().then(resolve), value.delay)
268
- : f.start().waitUntilStopped().then(resolve)
283
+ this.scheduledTransitions[prop] = {
284
+ v: props[prop],
285
+ f,
286
+ timeout: setTimeout(() => {
287
+ f.start()
288
+ .waitUntilStopped()
289
+ .then(() => delete this.scheduledTransitions[prop])
290
+ .then(resolve)
291
+ }, value.delay || 0),
292
+ }
269
293
  })
270
294
  }
271
295
  },
@@ -275,6 +299,7 @@ export default (config) =>
275
299
  Object.assign(Object.create(Element), {
276
300
  node: null,
277
301
  setProperties: [],
302
+ scheduledTransitions: {},
278
303
  initData: {},
279
304
  config,
280
305
  })
package/src/focus.js CHANGED
@@ -19,33 +19,46 @@ import symbols from './lib/symbols.js'
19
19
  import { navigating } from './router/router.js'
20
20
 
21
21
  let focusedComponent = null
22
+ let focusChain = []
23
+ let setFocusTimeout
22
24
 
23
25
  export default {
26
+ _hold: false,
27
+ set hold(v) {
28
+ this._hold = v
29
+ },
30
+ get hold() {
31
+ return this._hold
32
+ },
24
33
  get() {
25
34
  return focusedComponent
26
35
  },
27
36
  set(component, event) {
37
+ clearTimeout(setFocusTimeout)
38
+ focusedComponent && focusedComponent.unfocus()
39
+ focusChain.reverse().forEach((cmp) => cmp.unfocus())
28
40
  if (component !== focusedComponent) {
29
- if (focusedComponent && focusedComponent !== component.parent) {
30
- focusedComponent.unfocus()
31
- }
32
- focusedComponent = component
33
- focusedComponent.lifecycle.state = 'focus'
34
- if (event instanceof KeyboardEvent) {
35
- document.dispatchEvent(new KeyboardEvent('keydown', event))
36
- }
41
+ setFocusTimeout = setTimeout(
42
+ () => {
43
+ focusedComponent = component
44
+ focusedComponent.lifecycle.state = 'focus'
45
+ if (event instanceof KeyboardEvent) {
46
+ document.dispatchEvent(new KeyboardEvent('keydown', event))
47
+ } else {
48
+ focusChain = []
49
+ }
50
+ },
51
+ // todo: make the hold timeout configurable?
52
+ this.hold ? 50 : 0
53
+ )
37
54
  }
38
55
  },
39
56
  input(key, event) {
40
57
  if (navigating === true) return
41
- const focusChain = walkChain([focusedComponent], key)
58
+ focusChain = walkChain([focusedComponent], key)
42
59
  const componentWithInputEvent = focusChain.shift()
43
60
 
44
61
  if (componentWithInputEvent) {
45
- if (componentWithInputEvent !== focusedComponent) {
46
- focusChain.reverse().forEach((component) => component.unfocus())
47
- componentWithInputEvent.focus()
48
- }
49
62
  if (componentWithInputEvent[symbols.inputEvents][key]) {
50
63
  componentWithInputEvent[symbols.inputEvents][key].call(componentWithInputEvent, event)
51
64
  } else if (componentWithInputEvent[symbols.inputEvents].any) {