@lightningjs/blits 0.3.14 → 0.3.15

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
+ ## v0.3.15
4
+
5
+ _23 oct 2023_
6
+
7
+ - Added support for slots
8
+ - Added support for defining custom keymapping
9
+ - Improved error handling of the template parser
10
+
3
11
  ## v0.3.14
4
12
 
5
13
  _19 oct 2023_
@@ -31,6 +31,6 @@
31
31
  "vite": "^4.0.4"
32
32
  },
33
33
  "dependencies": {
34
- "@lightningjs/blits": "^0.3.14"
34
+ "@lightningjs/blits": "^0.3.15"
35
35
  }
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightningjs/blits",
3
- "version": "0.3.14",
3
+ "version": "0.3.15",
4
4
  "description": "Blits: The Lightning 3 App Development Framework",
5
5
  "bin": "bin/index.cjs",
6
6
  "exports": {
@@ -16,12 +16,11 @@
16
16
  */
17
17
 
18
18
  import Component from './component.js'
19
-
20
19
  import Focus from './focus.js'
20
+ import Settings from './settings.js'
21
21
 
22
22
  const Application = (config) => {
23
- // make configurable?
24
- const mapping = {
23
+ const defaultKeyMap = {
25
24
  ArrowLeft: 'left',
26
25
  ArrowRight: 'right',
27
26
  ArrowUp: 'up',
@@ -30,24 +29,37 @@ const Application = (config) => {
30
29
  ' ': 'space',
31
30
  Backspace: 'back',
32
31
  Escape: 'escape',
32
+ 37: 'left',
33
+ 39: 'right',
34
+ 38: 'up',
35
+ 40: 'down',
36
+ 13: 'enter',
37
+ 32: 'space',
38
+ 8: 'back',
39
+ 27: 'escape',
33
40
  }
34
41
 
35
- const handler = (e) => {
36
- const key = mapping[e.key] || e.key
37
- Focus.input(key, e)
38
- }
39
-
40
- document.addEventListener('keydown', handler)
41
-
42
42
  config.hooks = config.hooks || {}
43
- config.hooks.___init = function () {
44
- Focus.set(this)
45
- }
43
+
44
+ let handler
46
45
 
47
46
  config.hooks.___destroy = function () {
48
47
  document.removeEventListener('keydown', handler)
49
48
  }
50
49
 
50
+ config.hooks.___init = function () {
51
+ const keyMap = { ...defaultKeyMap, ...Settings.get('keymap', {}) }
52
+
53
+ handler = (e) => {
54
+ const key = keyMap[e.key] || keyMap[e.keyCode] || e.key || e.keyCode
55
+ Focus.input(key, e)
56
+ }
57
+
58
+ document.addEventListener('keydown', handler)
59
+
60
+ Focus.set(this)
61
+ }
62
+
51
63
  const App = Component('App', config)
52
64
 
53
65
  return App
package/src/component.js CHANGED
@@ -120,6 +120,12 @@ const Component = (name = required('name'), config = required('config')) => {
120
120
  this.parent = parentComponent
121
121
 
122
122
  Object.defineProperties(this, {
123
+ type: {
124
+ value: name,
125
+ writable: false,
126
+ enumerable: true,
127
+ configurable: false,
128
+ },
123
129
  componentId: {
124
130
  value: createHumanReadableId(name),
125
131
  writable: false,
@@ -158,6 +164,13 @@ const Component = (name = required('name'), config = required('config')) => {
158
164
  configurable: false,
159
165
  })
160
166
 
167
+ Object.defineProperty(this, '___slots', {
168
+ value: this.___children.filter((child) => child.___isSlot),
169
+ writable: false,
170
+ enumerable: false,
171
+ configurable: false,
172
+ })
173
+
161
174
  code.effects.forEach((eff) => {
162
175
  effect(() => {
163
176
  eff.apply(stage, [this, this.___children, code.context])
package/src/element.js CHANGED
@@ -174,6 +174,10 @@ const Element = {
174
174
  }
175
175
  this.initData = data
176
176
 
177
+ if (props.___isSlot) {
178
+ this.___isSlot = true
179
+ }
180
+
177
181
  transformations.remap(props)
178
182
  Object.keys(props).forEach((prop) => {
179
183
  if (transformations[prop]) {
package/src/launch.d.ts CHANGED
@@ -86,7 +86,11 @@ export interface Settings {
86
86
  /**
87
87
  * Fonts to be used in the Application
88
88
  */
89
- fonts?: Font[]
89
+ fonts?: Font[],
90
+ /**
91
+ * Custom keymapping
92
+ */
93
+ keymap?: object
90
94
  }
91
95
 
92
96
  /**
@@ -65,7 +65,18 @@ const generateElementCode = function (
65
65
  delete templateObject['children']
66
66
 
67
67
  Object.keys(templateObject).forEach((key) => {
68
- if (key === 'type') return
68
+ if (key === 'type') {
69
+ if (templateObject[key] === 'Slot') {
70
+ renderCode.push(`elementConfig${counter}['___isSlot'] = true`)
71
+ }
72
+ return
73
+ }
74
+
75
+ if (key === 'slot') {
76
+ renderCode.push(`
77
+ elementConfig${counter}['parent'] = component.___slots.filter(slot => slot.ref === '${templateObject.slot}').shift() || component.___slots[0] || parent
78
+ `)
79
+ }
69
80
 
70
81
  if (isReactiveKey(key)) {
71
82
  this.effectsCode.push(
@@ -116,6 +127,8 @@ const generateComponentCode = function (
116
127
  options.key = interpolate(templateObject.key, options.component)
117
128
  }
118
129
 
130
+ const children = templateObject.children
131
+ delete templateObject.children
119
132
  generateElementCode.call(this, templateObject, parent, { ...options, ...{ holder: true } })
120
133
 
121
134
  parent = options.key ? `elms[${counter}][${options.key}]` : `elms[${counter}]`
@@ -159,8 +172,17 @@ const generateComponentCode = function (
159
172
  renderCode.push(`
160
173
  if(!${elm}) {
161
174
  ${elm} = (context.components && context.components['${templateObject.type}'] || component.___components['${templateObject.type}'] || (() => { console.log('component ${templateObject.type} not found')})).call(null, {props: props${counter}}, ${parent}, component)
175
+ if (${elm}.___slots[0]) {
176
+ parent = ${elm}.___slots[0]
177
+ component = ${elm}
178
+ } else {
179
+ parent = ${elm}.___children[0]
180
+ }
162
181
  }
163
182
  `)
183
+
184
+ counter++
185
+ generateElementCode.call(this, { children }, false, { ...options })
164
186
  }
165
187
 
166
188
  const generateForLoopCode = function (templateObject, parent) {
@@ -210,14 +232,14 @@ const generateForLoopCode = function (templateObject, parent) {
210
232
  `)
211
233
  }
212
234
 
213
- if (templateObject.type !== 'Element') {
214
- generateComponentCode.call(ctx, templateObject, false, {
235
+ if (templateObject.type === 'Element' || templateObject.type === 'Slot') {
236
+ generateElementCode.call(ctx, templateObject, parent, {
215
237
  key: 'scope.key',
216
238
  component: 'scope.',
217
239
  forceEffect: false,
218
240
  })
219
241
  } else {
220
- generateElementCode.call(ctx, templateObject, parent, {
242
+ generateComponentCode.call(ctx, templateObject, false, {
221
243
  key: 'scope.key',
222
244
  component: 'scope.',
223
245
  forceEffect: false,
@@ -248,10 +270,10 @@ const generateCode = function (templateObject, parent = false) {
248
270
  if (Object.keys(childTemplateObject).indexOf(':for') > -1) {
249
271
  generateForLoopCode.call(this, childTemplateObject, parent)
250
272
  } else {
251
- if (childTemplateObject.type !== 'Element') {
252
- generateComponentCode.call(this, childTemplateObject, parent)
253
- } else {
273
+ if (childTemplateObject.type === 'Element' || childTemplateObject.type === 'Slot') {
254
274
  generateElementCode.call(this, childTemplateObject, parent)
275
+ } else {
276
+ generateComponentCode.call(this, childTemplateObject, parent)
255
277
  }
256
278
  }
257
279
  })
@@ -16,8 +16,8 @@
16
16
  */
17
17
 
18
18
  class TemplateParseError extends Error {
19
- constructor(name, context) {
20
- super('TemplateParseError')
19
+ constructor(message, name, context) {
20
+ super(`TemplateParseError ${message}`)
21
21
  this.name = name
22
22
  this.context = context
23
23
  }
@@ -44,7 +44,13 @@ export default (template = '') => {
44
44
  try {
45
45
  return format(tags)
46
46
  } catch (error) {
47
- console.error('Error:', error.message)
47
+ if (error instanceof TemplateParseError) {
48
+ console.error(`${error.message} | ${error.name}`)
49
+ } else {
50
+ console.error(error)
51
+ }
52
+ // return errors gracefully
53
+ return null
48
54
  }
49
55
  }
50
56