@lightningjs/blits 2.0.0-beta.1 → 2.0.0-beta.11
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 +83 -0
- package/README.md +2 -0
- package/element-test-full.txt +0 -0
- package/index.d.ts +169 -41
- package/package.json +28 -8
- package/scripts/lint.js +17 -0
- package/scripts/prepublishOnly.js +15 -6
- package/scripts/prepush.js +25 -7
- package/src/announcer/announcer.js +54 -6
- package/src/announcer/speechSynthesis.js +156 -37
- package/src/application.js +98 -3
- package/src/component/base/methods.js +5 -2
- package/src/component/base/router.js +6 -0
- package/src/component/base/timeouts_intervals.js +56 -0
- package/src/component/setup/routes.js +5 -0
- package/src/component/setup/state.js +2 -0
- package/src/component.js +64 -24
- package/src/components/Circle.js +5 -3
- package/src/components/FPScounter.js +1591 -1577
- package/src/components/RouterView.js +141 -124
- package/src/components/Sprite.js +65 -8
- package/src/components/index.js +0 -2
- package/src/constants.js +17 -0
- package/src/engine.js +17 -0
- package/src/engines/L3/element.js +101 -7
- package/src/engines/L3/fontLoader.js +17 -0
- package/src/engines/L3/index.js +17 -0
- package/src/engines/L3/launch.js +4 -1
- package/src/engines/L3/shaderLoader.js +17 -0
- package/src/engines/index.js +17 -0
- package/src/{focus.js → focus/focus.js} +6 -18
- package/src/focus/helpers.js +31 -0
- package/src/focus/hover.js +94 -0
- package/src/helpers/fetchJson.js +4 -6
- package/src/launch.js +1 -0
- package/src/lib/codegenerator/generator.js +55 -9
- package/src/lib/lifecycle.js +34 -3
- package/src/lib/log.js +4 -4
- package/src/lib/precompiler/precompiler.js +23 -14
- package/src/lib/reactivity/effect.js +3 -2
- package/src/lib/reactivityguard/computedprops.js +113 -28
- package/src/lib/shaders/shaders.js +2 -1
- package/src/lib/symbols.js +19 -0
- package/src/lib/utils.js +17 -0
- package/src/plugin.js +17 -0
- package/src/plugins/appstate.d.ts +26 -0
- package/src/plugins/index.d.ts +28 -0
- package/src/plugins/language.d.ts +37 -0
- package/src/plugins/storage/localCookie.js +4 -6
- package/src/plugins/storage/storage.d.ts +31 -0
- package/src/plugins/theme.d.ts +43 -0
- package/src/plugins/theme.js +30 -3
- package/src/router/router.js +78 -14
- package/test-output.txt +0 -0
- package/vite/inject-dev-config.js +17 -0
- package/vite/preCompiler.js +15 -5
- package/vscode/data/template-attributes.json +335 -86
package/src/router/router.js
CHANGED
|
@@ -21,7 +21,7 @@ import { reactive } from '../lib/reactivity/reactive.js'
|
|
|
21
21
|
import symbols from '../lib/symbols.js'
|
|
22
22
|
import { Log } from '../lib/log.js'
|
|
23
23
|
import { stage } from '../launch.js'
|
|
24
|
-
import Focus from '../focus.js'
|
|
24
|
+
import Focus from '../focus/focus.js'
|
|
25
25
|
import Announcer from '../announcer/announcer.js'
|
|
26
26
|
import Settings from '../settings.js'
|
|
27
27
|
|
|
@@ -30,6 +30,9 @@ import Settings from '../settings.js'
|
|
|
30
30
|
* @typedef {import('../component.js').BlitsComponent} BlitsComponent - The element of the route
|
|
31
31
|
* @typedef {import('../engines/L3/element.js').BlitsElement} BlitsElement - The element of the route
|
|
32
32
|
*
|
|
33
|
+
* @typedef {BlitsComponent|BlitsComponentFactory} RouteView
|
|
34
|
+
* @typedef {RouteView & { default?: BlitsComponentFactory }} RouteViewWithOptionalDefault
|
|
35
|
+
*
|
|
33
36
|
* @typedef {Object} Route
|
|
34
37
|
* @property {string} path - The path of the route
|
|
35
38
|
* @property {string} hash - The hash of the route
|
|
@@ -57,6 +60,7 @@ export const state = reactive(
|
|
|
57
60
|
data: null,
|
|
58
61
|
params: null,
|
|
59
62
|
hash: '',
|
|
63
|
+
backNavigation: true,
|
|
60
64
|
},
|
|
61
65
|
Settings.get('reactivityMode'),
|
|
62
66
|
true
|
|
@@ -212,12 +216,17 @@ const defaultOptions = {
|
|
|
212
216
|
}
|
|
213
217
|
|
|
214
218
|
const makeRouteObject = (route, overrides) => {
|
|
219
|
+
// FIX: exclude keepAlive from the destination route options. Unlike other
|
|
220
|
+
// overrides, keepAlive applies to the route being LEFT, not the destination.
|
|
221
|
+
// It is consumed by removeView() instead.
|
|
222
|
+
const { keepAlive: _keepAlive, ...destOverrides } = overrideOptions // eslint-disable-line no-unused-vars
|
|
223
|
+
|
|
215
224
|
const cleanRoute = {
|
|
216
225
|
hash: overrides.hash,
|
|
217
226
|
path: route.path,
|
|
218
227
|
component: route.component,
|
|
219
228
|
transition: 'transition' in route ? route.transition : fadeInFadeOutTransition,
|
|
220
|
-
options: { ...defaultOptions, ...route.options, ...
|
|
229
|
+
options: { ...defaultOptions, ...route.options, ...destOverrides },
|
|
221
230
|
announce: route.announce || false,
|
|
222
231
|
hooks: route.hooks || {},
|
|
223
232
|
data: { ...route.data, ...navigationData, ...overrides.queryParams },
|
|
@@ -247,7 +256,7 @@ export const navigate = async function () {
|
|
|
247
256
|
let reuse = false
|
|
248
257
|
if (preventHashChangeNavigation === false && this[symbols.parent][symbols.routes]) {
|
|
249
258
|
let previousRoute = currentRoute //? Object.assign({}, currentRoute) : undefined
|
|
250
|
-
let route = matchHash(getHash(
|
|
259
|
+
let route = matchHash(getHash(location.hash), this[symbols.parent][symbols.routes])
|
|
251
260
|
|
|
252
261
|
currentRoute = route
|
|
253
262
|
|
|
@@ -258,7 +267,11 @@ export const navigate = async function () {
|
|
|
258
267
|
const hooks = this[symbols.parent][symbols.routerHooks]
|
|
259
268
|
if (hooks.beforeEach) {
|
|
260
269
|
try {
|
|
261
|
-
beforeEachResult = await hooks.beforeEach.call(
|
|
270
|
+
beforeEachResult = await hooks.beforeEach.call(
|
|
271
|
+
this[symbols.parent],
|
|
272
|
+
route,
|
|
273
|
+
previousRoute
|
|
274
|
+
)
|
|
262
275
|
if (isString(beforeEachResult)) {
|
|
263
276
|
currentRoute = previousRoute
|
|
264
277
|
to(beforeEachResult)
|
|
@@ -299,7 +312,11 @@ export const navigate = async function () {
|
|
|
299
312
|
let beforeHookOutput
|
|
300
313
|
if (route.hooks.before) {
|
|
301
314
|
try {
|
|
302
|
-
beforeHookOutput = await route.hooks.before.call(
|
|
315
|
+
beforeHookOutput = await route.hooks.before.call(
|
|
316
|
+
this[symbols.parent],
|
|
317
|
+
route,
|
|
318
|
+
previousRoute
|
|
319
|
+
)
|
|
303
320
|
if (isString(beforeHookOutput)) {
|
|
304
321
|
currentRoute = previousRoute
|
|
305
322
|
to(beforeHookOutput)
|
|
@@ -335,10 +352,15 @@ export const navigate = async function () {
|
|
|
335
352
|
return
|
|
336
353
|
}
|
|
337
354
|
}
|
|
355
|
+
|
|
338
356
|
// add the previous route (technically still the current route at this point)
|
|
339
357
|
// into the history stack when inHistory is true and we're not navigating back
|
|
358
|
+
//
|
|
359
|
+
// FIX: use truthy check instead of `!== undefined` because matchHash()
|
|
360
|
+
// can return `false`, which survives `!== undefined` but has no `.options`.
|
|
340
361
|
if (
|
|
341
|
-
previousRoute
|
|
362
|
+
previousRoute &&
|
|
363
|
+
previousRoute.options &&
|
|
342
364
|
previousRoute.options.inHistory === true &&
|
|
343
365
|
navigatingBack === false
|
|
344
366
|
) {
|
|
@@ -354,6 +376,7 @@ export const navigate = async function () {
|
|
|
354
376
|
/** @type {import('../engines/L3/element.js').BlitsElement} */
|
|
355
377
|
let holder
|
|
356
378
|
|
|
379
|
+
/** @type {RouteViewWithOptionalDefault|undefined|null} */
|
|
357
380
|
let view
|
|
358
381
|
let focus
|
|
359
382
|
// when navigating back let's see if we're navigating back to a route that was kept alive
|
|
@@ -397,7 +420,7 @@ export const navigate = async function () {
|
|
|
397
420
|
// Update router state after announcements and final route resolution,
|
|
398
421
|
// right before initializing or restoring the view
|
|
399
422
|
state.path = route.path
|
|
400
|
-
state.params = route.params
|
|
423
|
+
state.params = Object.keys(route.params).length === 0 ? null : route.params
|
|
401
424
|
state.hash = route.hash
|
|
402
425
|
state.data = null
|
|
403
426
|
state.data = route.data || {}
|
|
@@ -479,12 +502,13 @@ export const navigate = async function () {
|
|
|
479
502
|
|
|
480
503
|
// apply out out transition on previous view if available, unless
|
|
481
504
|
// we're reusing the prvious page component
|
|
482
|
-
|
|
505
|
+
// FIX: truthy guard — previousRoute can be `false` (see history-push comment above).
|
|
506
|
+
if (previousRoute && reuse === false) {
|
|
483
507
|
// only animate when there is a previous route
|
|
484
508
|
shouldAnimate = true
|
|
485
509
|
const oldView = this[symbols.children].splice(1, 1).pop()
|
|
486
510
|
if (oldView) {
|
|
487
|
-
removeView(previousRoute, oldView, route.transition.out, navigatingBack)
|
|
511
|
+
await removeView(previousRoute, oldView, route.transition.out, navigatingBack)
|
|
488
512
|
}
|
|
489
513
|
}
|
|
490
514
|
|
|
@@ -492,7 +516,7 @@ export const navigate = async function () {
|
|
|
492
516
|
if (route.transition.in) {
|
|
493
517
|
if (Array.isArray(route.transition.in)) {
|
|
494
518
|
for (let i = 0; i < route.transition.in.length; i++) {
|
|
495
|
-
i === route.transition.length - 1
|
|
519
|
+
i === route.transition.in.length - 1
|
|
496
520
|
? await setOrAnimate(holder, route.transition.in[i], shouldAnimate)
|
|
497
521
|
: setOrAnimate(holder, route.transition.in[i], shouldAnimate)
|
|
498
522
|
}
|
|
@@ -500,6 +524,33 @@ export const navigate = async function () {
|
|
|
500
524
|
await setOrAnimate(holder, route.transition.in, shouldAnimate)
|
|
501
525
|
}
|
|
502
526
|
}
|
|
527
|
+
|
|
528
|
+
if (this[symbols.parent][symbols.routerHooks]) {
|
|
529
|
+
const hooks = this[symbols.parent][symbols.routerHooks]
|
|
530
|
+
if (hooks.afterEach) {
|
|
531
|
+
try {
|
|
532
|
+
await hooks.afterEach.call(
|
|
533
|
+
this[symbols.parent],
|
|
534
|
+
route, // to
|
|
535
|
+
previousRoute // from
|
|
536
|
+
)
|
|
537
|
+
} catch (error) {
|
|
538
|
+
Log.error('Error in "AfterEach" Hook', error)
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
if (route.hooks.after) {
|
|
544
|
+
try {
|
|
545
|
+
await route.hooks.after.call(
|
|
546
|
+
this[symbols.parent],
|
|
547
|
+
route, // to
|
|
548
|
+
previousRoute // from
|
|
549
|
+
)
|
|
550
|
+
} catch (error) {
|
|
551
|
+
Log.error('Error or Rejected Promise in "After" Hook', error)
|
|
552
|
+
}
|
|
553
|
+
}
|
|
503
554
|
} else {
|
|
504
555
|
Log.error(`Route ${route.hash} not found`)
|
|
505
556
|
const routerHooks = this[symbols.parent][symbols.routerHooks]
|
|
@@ -509,6 +560,12 @@ export const navigate = async function () {
|
|
|
509
560
|
}
|
|
510
561
|
}
|
|
511
562
|
|
|
563
|
+
// Clear module-level variables after removeView has consumed them.
|
|
564
|
+
// Placed here so it executes for all navigation flows, not only when
|
|
565
|
+
// previousRoute exists and reuse is false.
|
|
566
|
+
overrideOptions = {}
|
|
567
|
+
navigationData = {}
|
|
568
|
+
|
|
512
569
|
// reset navigating indicators
|
|
513
570
|
navigatingBack = false
|
|
514
571
|
state.navigating = false
|
|
@@ -536,11 +593,18 @@ const removeView = async (route, view, transition, navigatingBack) => {
|
|
|
536
593
|
}
|
|
537
594
|
}
|
|
538
595
|
|
|
596
|
+
// Resolve effective keepAlive: runtime override from $router.to() takes precedence
|
|
597
|
+
// over the static route config option
|
|
598
|
+
const keepAlive =
|
|
599
|
+
overrideOptions.keepAlive !== undefined
|
|
600
|
+
? overrideOptions.keepAlive
|
|
601
|
+
: route.options && route.options.keepAlive
|
|
602
|
+
|
|
539
603
|
// cache the page when it's as 'keepAlive' instead of destroying
|
|
540
604
|
if (
|
|
541
605
|
navigatingBack === false &&
|
|
542
606
|
route.options &&
|
|
543
|
-
|
|
607
|
+
keepAlive === true &&
|
|
544
608
|
route.options.inHistory === true
|
|
545
609
|
) {
|
|
546
610
|
const historyItem = history[history.length - 1]
|
|
@@ -555,7 +619,7 @@ const removeView = async (route, view, transition, navigatingBack) => {
|
|
|
555
619
|
* 2. Navigating back, and the previous route is configured with "keep alive" set to true.
|
|
556
620
|
* 3. Navigating back, and the previous route is not configured with "keep alive" set to true.
|
|
557
621
|
*/
|
|
558
|
-
if (route.options && (
|
|
622
|
+
if (route.options && (keepAlive !== true || navigatingBack === true)) {
|
|
559
623
|
view.destroy()
|
|
560
624
|
view = null
|
|
561
625
|
}
|
|
@@ -585,11 +649,11 @@ const setOrAnimate = (node, transition, shouldAnimate = true) => {
|
|
|
585
649
|
})
|
|
586
650
|
}
|
|
587
651
|
|
|
588
|
-
export const to = (
|
|
652
|
+
export const to = (path, data = {}, options = {}) => {
|
|
589
653
|
navigationData = data
|
|
590
654
|
overrideOptions = options
|
|
591
655
|
|
|
592
|
-
|
|
656
|
+
location.hash = path.replace(/^#/, '')
|
|
593
657
|
}
|
|
594
658
|
|
|
595
659
|
export const back = function () {
|
package/test-output.txt
ADDED
|
Binary file
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2025 Comcast Cable Communications Management, LLC
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*
|
|
15
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
16
|
+
*/
|
|
17
|
+
|
|
1
18
|
export default function injectDevFlag() {
|
|
2
19
|
return {
|
|
3
20
|
name: 'inject-dev-config',
|
package/vite/preCompiler.js
CHANGED
|
@@ -32,12 +32,22 @@ export default function () {
|
|
|
32
32
|
|
|
33
33
|
// we should only precompile .blits, .js and .ts files
|
|
34
34
|
if (
|
|
35
|
-
|
|
36
|
-
fileExtension === '.
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
filePath.indexOf('node_modules') === -1 &&
|
|
36
|
+
(fileExtension === '.js' ||
|
|
37
|
+
fileExtension === '.ts' ||
|
|
38
|
+
fileExtension === '.blits' ||
|
|
39
|
+
fileExtension === '.mjs')
|
|
39
40
|
) {
|
|
40
|
-
|
|
41
|
+
const result = compiler(source, filePath, config.mode)
|
|
42
|
+
|
|
43
|
+
if (typeof result === 'object') {
|
|
44
|
+
return {
|
|
45
|
+
code: result.code,
|
|
46
|
+
map: result.map,
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// No transformation needed - return null so Vite knows no changes were made
|
|
50
|
+
return null
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
// vite expects null if there is no modification
|