@lightningjs/blits 0.9.8 → 0.10.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/boilerplate/common/public/fonts/Lato-Regular.ttf +0 -0
  3. package/boilerplate/common/public/fonts/Raleway-ExtraBold.ttf +0 -0
  4. package/docs/transitions_animations/transitions.md +3 -3
  5. package/package.json +3 -4
  6. package/src/application.d.ts +10 -10
  7. package/src/component/base/announcer.js +27 -0
  8. package/src/component/base/events.js +37 -0
  9. package/src/component/base/index.js +29 -0
  10. package/src/component/base/log.js +27 -0
  11. package/src/component/base/methods.js +136 -0
  12. package/src/component/base/router.js +40 -0
  13. package/src/component/base/timeouts_intervals.js +92 -0
  14. package/src/component/base/utils.js +29 -0
  15. package/src/{lib → component}/setup/computed.js +3 -3
  16. package/src/component/setup/index.js +61 -0
  17. package/src/{lib → component}/setup/input.js +4 -4
  18. package/src/{lib → component}/setup/methods.js +3 -3
  19. package/src/{lib → component}/setup/props.js +3 -3
  20. package/src/{lib → component}/setup/routes.js +3 -3
  21. package/src/{lib → component}/setup/state.js +13 -6
  22. package/src/{lib → component}/setup/watch.js +5 -5
  23. package/src/component.d.ts +157 -38
  24. package/src/component.js +145 -154
  25. package/src/components/Circle.js +5 -5
  26. package/src/components/FPScounter.js +249 -185
  27. package/src/components/Image.js +2 -2
  28. package/src/components/RouterView.js +1 -1
  29. package/src/components/Sprite.js +5 -5
  30. package/src/components/Sprite.orig.js +2 -2
  31. package/src/components/Text.js +11 -11
  32. package/src/components/index.js +32 -0
  33. package/src/components/index.orig.js +32 -0
  34. package/src/engines/L3/element.js +41 -35
  35. package/src/engines/L3/fontLoader.js +16 -2
  36. package/src/engines/L3/launch.js +1 -1
  37. package/src/lib/codegenerator/generator.js +18 -8
  38. package/vite/msdfGenerator.js +52 -53
  39. package/boilerplate/common/public/fonts/Lato-Regular.msdf.json +0 -5383
  40. package/boilerplate/common/public/fonts/Lato-Regular.msdf.png +0 -0
  41. package/boilerplate/common/public/fonts/Raleway-ExtraBold.msdf.json +0 -10838
  42. package/boilerplate/common/public/fonts/Raleway-ExtraBold.msdf.png +0 -0
  43. package/src/lib/setup/base.js +0 -288
  44. /package/src/{lib → component}/setup/props.test.js +0 -0
@@ -15,9 +15,9 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
- import { Log } from '../log.js'
18
+ import { Log } from '../../lib/log.js'
19
19
 
20
- import symbols from '../symbols.js'
20
+ import symbols from '../../lib/symbols.js'
21
21
 
22
22
  export default (component, methods) => {
23
23
  component[symbols.methodKeys] = []
@@ -31,7 +31,7 @@ export default (component, methods) => {
31
31
  Log.warn(`${method} is not a function`)
32
32
  }
33
33
  component[symbols.methodKeys].push(method)
34
- component.prototype[method] = methods[method]
34
+ component[method] = methods[method]
35
35
  }
36
36
  }
37
37
  }
@@ -15,9 +15,9 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
- import { Log } from '../log.js'
18
+ import { Log } from '../../lib/log.js'
19
19
 
20
- import symbols from '../symbols.js'
20
+ import symbols from '../../lib/symbols.js'
21
21
 
22
22
  const baseProp = {
23
23
  cast: (v) => v,
@@ -32,7 +32,7 @@ export default (component, props = []) => {
32
32
  props.forEach((prop) => {
33
33
  prop = { ...baseProp, ...(typeof prop === 'object' ? prop : { key: prop }) }
34
34
  component[symbols.propKeys].push(prop.key)
35
- Object.defineProperty(component.prototype, prop.key, {
35
+ Object.defineProperty(component, prop.key, {
36
36
  get() {
37
37
  const value = prop.cast(
38
38
  this[symbols.props] && prop.key in this[symbols.props]
@@ -15,13 +15,13 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
- import symbols from '../symbols.js'
18
+ import symbols from '../../lib/symbols.js'
19
19
 
20
20
  export default (component, routes) => {
21
- component.prototype[symbols.routes] = []
21
+ component[symbols.routes] = []
22
22
  Object.keys(routes).forEach((key) => {
23
23
  // todo: validate routes[key] for expected format etc.
24
- component.prototype[symbols.routes][key] = {
24
+ component[symbols.routes][key] = {
25
25
  ...routes[key],
26
26
  ...{
27
27
  // merge default route options with route specific options
@@ -15,15 +15,21 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
- import { Log } from '../log.js'
18
+ import { Log } from '../../lib/log.js'
19
19
 
20
- import symbols from '../symbols.js'
20
+ import symbols from '../../lib/symbols.js'
21
21
 
22
22
  export default (component, state = () => {}) => {
23
- component[symbols.stateKeys] = []
23
+ Object.defineProperty(component, symbols.stateKeys, {
24
+ value: [],
25
+ enumerable: false,
26
+ configurable: false,
27
+ writable: false,
28
+ })
29
+
30
+ const stateKeys = Object.keys(state.apply(component) || {}).concat(['hasFocus'])
24
31
 
25
- state = { ...state.apply(component.prototype), ...{ hasFocus: false } }
26
- Object.keys(state).forEach((key) => {
32
+ stateKeys.forEach((key) => {
27
33
  if (component[symbols.propKeys] && component[symbols.propKeys].indexOf(key) > -1) {
28
34
  Log.error(`State ${key} already exists as a prop`)
29
35
  }
@@ -32,13 +38,14 @@ export default (component, state = () => {}) => {
32
38
  }
33
39
  component[symbols.stateKeys].push(key)
34
40
  try {
35
- Object.defineProperty(component.prototype, key, {
41
+ Object.defineProperty(component, key, {
36
42
  get() {
37
43
  return this[symbols.state] && key in this[symbols.state] && this[symbols.state][key]
38
44
  },
39
45
  set(v) {
40
46
  if (this[symbols.state]) this[symbols.state][key] = v
41
47
  },
48
+ // enumerable: true,
42
49
  })
43
50
  } catch (e) {
44
51
  Log.error(e)
@@ -15,20 +15,20 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
- import symbols from '../symbols.js'
18
+ import symbols from '../../lib/symbols.js'
19
19
 
20
20
  export default (component, watchers) => {
21
- component.prototype[symbols.watchKeys] = []
22
- component.prototype[symbols.watchers] = {}
21
+ component[symbols.watchKeys] = []
22
+ component[symbols.watchers] = {}
23
23
 
24
24
  for (let watch in watchers) {
25
25
  if (typeof watchers[watch] !== 'function') {
26
26
  console.warn(`${watch} is not a function`)
27
27
  }
28
28
 
29
- component.prototype[symbols.watchKeys].push(watch)
29
+ component[symbols.watchKeys].push(watch)
30
30
 
31
- component.prototype[symbols.watchers][watch] = function (v, old) {
31
+ component[symbols.watchers][watch] = function (v, old) {
32
32
  watchers[watch].call(this, v, old)
33
33
  }
34
34
  }
@@ -22,6 +22,47 @@ declare namespace Component {
22
22
  */
23
23
  type Name = string
24
24
 
25
+
26
+ interface Announcer {
27
+ /**
28
+ * Announce a message to screen readers by specifying the politeness level
29
+ */
30
+ speak: (message: string, politeness?: 'polite' | 'assertive') => void
31
+
32
+ /**
33
+ * Announce a message to screen readers with a polite politeness level
34
+ */
35
+ polite: (message: string) => void
36
+
37
+ /**
38
+ * Announce a message to screen readers with an assertive politeness level
39
+ */
40
+ assertive: (message: string) => void
41
+
42
+ /**
43
+ * Stop all announcements
44
+ */
45
+ stop: () => void
46
+ }
47
+
48
+ interface Log {
49
+ /**
50
+ * Log an info message
51
+ */
52
+ info(...args): typeof console.info
53
+ /**
54
+ * Log an error message
55
+ */
56
+ error(...args): typeof console.error
57
+ /**
58
+ * Log a warning
59
+ */
60
+ warn(...args): typeof console.warn
61
+ /**
62
+ * Log a debug message
63
+ */
64
+ debug(...args): typeof console.debug
65
+ }
25
66
  interface AdvancedProp {
26
67
  /**
27
68
  * Name of the prop
@@ -48,115 +89,175 @@ declare namespace Component {
48
89
  */
49
90
  cast?: () => any
50
91
  }
92
+ type PropsArray<T extends string> = T[]
93
+ type AdvancedProps = AdvancedProp[]
51
94
 
52
- type Props = string | AdvancedProp
95
+ // type ExtractPropNames<T extends Prop[]> = T extends (infer U)[]
96
+ // ? U extends string
97
+ // ? U
98
+ // : U extends AdvancedProp
99
+ // ? U['key']
100
+ // : never
101
+ // : never;
53
102
 
54
103
  type NotFunction<T> = T extends Function ? never : T;
55
104
 
56
105
  /**
57
106
  * Internal state of a Component instance
58
107
  */
59
- interface StateObject {
108
+ interface State {
60
109
  [key: string]: any
61
110
  }
62
111
 
63
- interface Computed {
64
- [key: string]: (this: ComponentInstance) => any
112
+ interface Computed<S, M, P> {
113
+ [key: string]: (this: ComponentInstance & S & M & P) => any
65
114
  }
66
115
 
67
- interface Watch {
68
- [key: string]: (this: ComponentInstance, value: any, oldValue: any) => void
116
+ interface Watch<S, M, P> {
117
+ [key: string]: (this: ComponentInstance & S & M & P, value: any, oldValue: any) => void
69
118
  }
70
119
 
71
120
  interface Methods {
72
- [key: string]: (this: ComponentInstance) => any
121
+ [key: string]: (this: ComponentInstance & State & Methods, ...args: any) => any;
73
122
  }
74
123
 
75
- interface Input {
76
- [key: string]: (this: ComponentInstance, event: KeyboardEvent) => void,
124
+ // interface MethodsExtended<S, M, P> extends Methods {
125
+ // [key: string]: (this: ComponentInstance & S & M & P) => any;
126
+ // }
127
+
128
+ interface Input<S, M, P> {
129
+ [key: string]: ((this: ComponentInstance & S & M & P, event: KeyboardEvent) => void) | undefined,
130
+
77
131
  /**
78
132
  * Catch all input function
79
133
  *
80
134
  * Will be invoked when there is no dedicated function for a certain key
81
- */
82
- 'any'?: (this: ComponentInstance, event: KeyboardEvent) => void,
135
+ */
136
+ any?: (this: ComponentInstance & S & M & P, event: KeyboardEvent) => void,
83
137
  }
84
138
 
85
139
  interface Log {
86
140
  /**
87
141
  * Log an info message
88
142
  */
89
- info: typeof console.info
143
+ info(...args): typeof console.info
90
144
  /**
91
145
  * Log an error message
92
146
  */
93
- error: typeof console.error
147
+ error(...args): typeof console.error
94
148
  /**
95
149
  * Log a warning
96
150
  */
97
- warn: typeof console.warn
151
+ warn(...args): typeof console.warn
98
152
  /**
99
153
  * Log a debug message
100
154
  */
101
- debug: typeof console.debug
155
+ debug(...args): typeof console.debug
102
156
  }
103
157
 
104
- interface Hooks {
158
+ interface Hooks<S, M, P> {
105
159
  /**
106
160
  * Fires when the Component is being instantiated.
107
161
  * At this moment child elements will not be available yet
108
162
  */
109
- init?: (this: ComponentInstance) => void
163
+ init?: (this: ComponentInstance & S & M & P, ...args: any) => void
110
164
  /**
111
165
  * Fires when the Component is fully initialized and ready for interaction.
112
166
  */
113
- ready?: (this: ComponentInstance) => void
167
+ ready?: (this: ComponentInstance & S & M & P, ...args: any) => void
114
168
  /**
115
169
  * Triggers when the Component receives focus.
116
170
  *
117
171
  * This event can fire multiple times during the component's lifecycle
118
172
  */
119
- focus?: (this: ComponentInstance) => void
173
+ focus?: (this: ComponentInstance & S & M & P, ...args: any) => void
120
174
  /**
121
175
  * Triggers when the Component loses focus.
122
176
  *
123
177
  * This event can fire multiple times during the component's lifecycle
124
178
  */
125
- unfocus?: (this: ComponentInstance) => void
179
+ unfocus?: (this: ComponentInstance & S & M & P, ...args: any) => void
126
180
  /**
127
181
  * Fires when the Component is being destroyed and removed.
128
182
  */
129
- destroy?: (this: ComponentInstance) => void,
183
+ destroy?: (this: ComponentInstance & S & M & P, ...args: any) => void,
130
184
  /**
131
185
  * Fires upon each frame start (allowing you to tap directly into the renderloop)
132
186
  *
133
187
  * Note: This hook will fire continuously, multiple times per second!
134
188
  */
135
- frameTick?: (this: ComponentInstance) => void,
189
+ frameTick?: (this: ComponentInstance & S & M & P, ...args: any) => void,
136
190
  /**
137
191
  * Fires when the component enters the viewport _margin_ and is attached to the render tree
138
192
  *
139
193
  * This event can fire multiple times during the component's lifecycle
140
194
  */
141
- attach?: (this: ComponentInstance) => void,
195
+ attach?: (this: ComponentInstance & S & M & P, ...args: any) => void,
142
196
  /**
143
197
  * Fires when the component leaves the viewport _margin_ and is detached from the render tree
144
198
  *
145
199
  * This event can fire multiple times during the component's lifecycle
146
200
  */
147
- detach?: (this: ComponentInstance) => void,
201
+ detach?: (this: ComponentInstance & S & M & P, ...args: any) => void,
148
202
  /**
149
203
  * Fires when the component enters the visible viewport
150
204
  *
151
205
  * This event can fire multiple times during the component's lifecycle
152
206
  */
153
- enter?: (this: ComponentInstance) => void,
207
+ enter?: (this: ComponentInstance & S & M & P, ...args: any) => void,
154
208
  /**
155
209
  * Fires when the component leaves the visible viewport
156
210
  *
157
211
  * This event can fire multiple times during the component's lifecycle
158
212
  */
159
- exit?: (this: ComponentInstance) => void,
213
+ exit?: (this: ComponentInstance & S & M & P, ...args: any) => void,
214
+ }
215
+
216
+ /**
217
+ * Route object
218
+ */
219
+ interface Route {
220
+ path: string,
221
+ params: Record<string, string>,
222
+ options?: {
223
+ inHistory?: boolean,
224
+ keepAlive?: boolean,
225
+ [key: string]: any,
226
+ },
227
+ data?: Record<string, any>,
228
+ component?: (args: { props: any }, holder: any, context: any) => Promise<any>,
229
+ hooks?: {
230
+ before?: (route: Route, previousRoute: Route) => Promise<string | Route | void>,
231
+ }
232
+ }
233
+
234
+
235
+ interface Router {
236
+ /**
237
+ * Navigate to a different location
238
+ */
239
+ to(location: string, data?: Record<string, any>, options?: Record<string, any>): void;
240
+
241
+ /**
242
+ * Navigate to the previous location
243
+ */
244
+ back(): boolean;
245
+
246
+ /**
247
+ * Get the current route read-only
248
+ */
249
+ readonly currentRoute: Route;
250
+
251
+ /**
252
+ * Get the list of all routes
253
+ */
254
+ readonly routes: Route[];
255
+
256
+ /**
257
+ * Get navigating state
258
+ */
259
+ readonly navigating: boolean;
260
+
160
261
  }
161
262
 
162
263
  export interface ComponentInstance {
@@ -217,15 +318,29 @@ declare namespace Component {
217
318
  */
218
319
  select: (ref: string) => ComponentInstance | ElementInstance
219
320
 
220
- // tmp
221
- [key: string]: any
321
+ /**
322
+ * Announcer methods for screen reader support
323
+ */
324
+ $announcer: Announcer
325
+
326
+ /**
327
+ * Triggers a forced update on state variables.
328
+ */
329
+ $trigger: (key: string) => void
330
+ trigger: (key: string) => void
331
+
332
+ /**
333
+ * Router instance
334
+ */
335
+ $router: Router
336
+
222
337
  }
223
338
 
224
339
  export interface ElementInstance {
225
340
  focus?: () => void
226
341
  }
227
342
 
228
- export interface ComponentConfig {
343
+ export interface ComponentConfig<Props extends string, S, M> {
229
344
  components?: any,
230
345
  /**
231
346
  * XML-based template string of the Component
@@ -261,7 +376,7 @@ declare namespace Component {
261
376
  * }
262
377
  * ```
263
378
  */
264
- state?: (this: ComponentInstance) => StateObject,
379
+ state?: (this: { [K in Props]: any}) => S,
265
380
  /**
266
381
  * Allowed props to be passed into the Component by the parent
267
382
  *
@@ -279,27 +394,27 @@ declare namespace Component {
279
394
  * }]
280
395
  * ```
281
396
  */
282
- props?: Props[],
397
+ props?: PropsArray<Props> | AdvancedProp[],
283
398
  /**
284
399
  * Computed properties
285
400
  */
286
- computed?: Computed,
401
+ computed?: Computed<S, M, { [K in Props]: any}>,
287
402
  /**
288
403
  * Watchers for changes to state variables, props or computed properties
289
404
  */
290
- watch?: Watch,
405
+ watch?: Watch<S, M, { [K in Props]: any}>,
291
406
  /**
292
407
  * Hooking into Lifecycle events
293
408
  */
294
- hooks?: Hooks,
409
+ hooks?: Hooks<S, M, { [K in Props]: any}>,
295
410
  /**
296
411
  * Methods for abstracting more complex business logic into separate function
297
412
  */
298
- methods?: Methods,
413
+ methods?: M //MethodsExtended<S, M, { [K in Props]: any}>,
299
414
  /**
300
415
  * Tapping into user input
301
416
  */
302
- input?: Input
417
+ input?: Input<S, M, { [K in Props]: any}>
303
418
  }
304
419
  }
305
420
 
@@ -307,9 +422,13 @@ declare namespace Component {
307
422
  /**
308
423
  * Blits.Component()
309
424
  */
310
- declare function Component(
425
+ declare function Component<
426
+ Props extends string,
427
+ S extends Component.State,
428
+ M extends Component.Methods
429
+ >(
311
430
  name: Component.Name,
312
- config: Component.ComponentConfig,
431
+ config: Component.ComponentConfig<Props, S, M>
313
432
  ) : Component.ComponentInstance
314
433
 
315
434
  export default Component;