@lightningjs/blits 0.5.0 → 0.5.2

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,4 +1,18 @@
1
1
  # Changelog
2
+ # v0.5.2
3
+
4
+ _30 nov 2023_
5
+
6
+ - Fixed issue in code generator leading to creation unnecessary child nodes
7
+ - Added focus handler to router view (that passes focus to the current active page)
8
+
9
+ # v0.5.1
10
+
11
+ _29 nov 2023_
12
+
13
+ - Fixed issue with unexpected unfocus
14
+ - Added fastforward of transitions on the same property
15
+ - Added functionality to skip focus change on key hold
2
16
 
3
17
  # v0.5.0
4
18
 
@@ -9,7 +9,7 @@
9
9
  "lint": "eslint '**/*.js'",
10
10
  "lint:fix": "eslint '**/*.js' --fix",
11
11
  "build": "vite build",
12
- "dev": "vite dev"
12
+ "dev": "vite dev --host"
13
13
  },
14
14
  "lint-staged": {
15
15
  "*.js": [
@@ -31,6 +31,6 @@
31
31
  "vite": "^4.0.4"
32
32
  },
33
33
  "dependencies": {
34
- "@lightningjs/blits": "^0.5.0"
34
+ "@lightningjs/blits": "^0.5.2"
35
35
  }
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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))
@@ -25,6 +25,11 @@ export default () =>
25
25
  template: `
26
26
  <Element w="100%" height="100%"></Element>
27
27
  `,
28
+ state() {
29
+ return {
30
+ activeView: null,
31
+ }
32
+ },
28
33
  hooks: {
29
34
  ready() {
30
35
  handler = () => Router.navigate.apply(this)
@@ -34,5 +39,8 @@ export default () =>
34
39
  destroy() {
35
40
  window.removeEventListener('hashchange', handler, false)
36
41
  },
42
+ focus() {
43
+ this.activeView && this.activeView.focus()
44
+ },
37
45
  },
38
46
  })
package/src/element.js CHANGED
@@ -248,6 +248,15 @@ const Element = {
248
248
  return this.initData.ref || null
249
249
  },
250
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
+
251
260
  const props = {}
252
261
  props[prop] = transformations.unpackTransition(value)
253
262
 
@@ -271,9 +280,16 @@ const Element = {
271
280
  typeof value === 'object' ? ('function' in value ? value.function : 'ease') : 'ease',
272
281
  })
273
282
  return new Promise((resolve) => {
274
- value.delay
275
- ? setTimeout(() => f.start().waitUntilStopped().then(resolve), value.delay)
276
- : 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
+ }
277
293
  })
278
294
  }
279
295
  },
@@ -283,6 +299,7 @@ export default (config) =>
283
299
  Object.assign(Object.create(Element), {
284
300
  node: null,
285
301
  setProperties: [],
302
+ scheduledTransitions: {},
286
303
  initData: {},
287
304
  config,
288
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) {
@@ -182,7 +182,9 @@ const generateComponentCode = function (
182
182
  `)
183
183
 
184
184
  counter++
185
- generateElementCode.call(this, { children }, false, { ...options })
185
+ if (children) {
186
+ generateElementCode.call(this, { children }, false, { ...options })
187
+ }
186
188
  }
187
189
 
188
190
  const generateForLoopCode = function (templateObject, parent) {
@@ -123,6 +123,7 @@ export const navigate = async function () {
123
123
 
124
124
  // focus the new view
125
125
  focus ? Focus.set(focus) : view.focus()
126
+ this.activeView = this[symbols.children][this[symbols.children].length - 1]
126
127
  } else {
127
128
  Log.error(`Route ${hash} not found`)
128
129
  }