@lightningjs/blits 2.0.0-beta.1 → 2.0.0-beta.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 +57 -0
- package/README.md +2 -0
- package/element-test-full.txt +0 -0
- package/index.d.ts +71 -7
- package/package.json +23 -3
- package/scripts/prepublishOnly.js +11 -2
- package/scripts/prepush.js +21 -1
- package/src/announcer/announcer.js +50 -4
- package/src/announcer/speechSynthesis.js +156 -37
- package/src/component/base/methods.js +4 -0
- 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.js +7 -1
- package/src/components/Circle.js +1 -0
- package/src/components/FPScounter.js +1 -0
- package/src/components/RouterView.js +139 -123
- package/src/components/Sprite.js +13 -7
- package/src/engines/L3/element.js +92 -7
- package/src/lib/codegenerator/generator.js +40 -8
- package/src/lib/lifecycle.js +29 -3
- package/src/lib/precompiler/precompiler.js +23 -14
- package/src/lib/reactivity/effect.js +3 -2
- package/src/lib/reactivityguard/computedprops.js +85 -14
- package/src/lib/shaders/shaders.js +2 -1
- package/src/lib/symbols.js +2 -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/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 +36 -3
- package/test-output.txt +0 -0
- package/vite/preCompiler.js +15 -5
|
@@ -19,33 +19,61 @@ import { Log } from '../lib/log.js'
|
|
|
19
19
|
|
|
20
20
|
const syn = window.speechSynthesis
|
|
21
21
|
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
const utterances = new Map() // Strong references with unique keys
|
|
22
|
+
const utterances = new Map() // id -> { utterance, timer, ignoreResume }
|
|
25
23
|
|
|
26
24
|
let initialized = false
|
|
27
|
-
let infinityTimer = null
|
|
28
25
|
|
|
29
|
-
const clear = () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
const clear = (id) => {
|
|
27
|
+
const state = utterances.get(id)
|
|
28
|
+
if (state === undefined) {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
if (state.timer !== null) {
|
|
32
|
+
clearTimeout(state.timer)
|
|
33
|
+
state.timer = null
|
|
33
34
|
}
|
|
35
|
+
utterances.delete(id)
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const startKeepAlive = (id) => {
|
|
39
|
+
const state = utterances.get(id)
|
|
40
|
+
|
|
41
|
+
// utterance status: utterance was removed (cancelled or finished)
|
|
42
|
+
if (state == undefined) {
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Clear existing timer for this specific utterance
|
|
47
|
+
if (state.timer !== null) {
|
|
48
|
+
clearTimeout(state.timer)
|
|
49
|
+
state.timer = null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// syn status: syn might be undefined or cancelled
|
|
53
|
+
if (!syn) {
|
|
54
|
+
clear(id)
|
|
55
|
+
return
|
|
39
56
|
}
|
|
40
57
|
|
|
41
58
|
syn.pause()
|
|
42
59
|
setTimeout(() => {
|
|
43
|
-
|
|
60
|
+
// utterance status: utterance might have been removed during setTimeout
|
|
61
|
+
const currentState = utterances.get(id)
|
|
62
|
+
if (currentState) {
|
|
63
|
+
currentState.ignoreResume = true
|
|
64
|
+
syn.resume()
|
|
65
|
+
}
|
|
44
66
|
}, 0)
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
68
|
+
// Check if utterance still exists before scheduling next cycle
|
|
69
|
+
if (utterances.has(id) === true) {
|
|
70
|
+
state.timer = setTimeout(() => {
|
|
71
|
+
// Double-check utterance still exists before resuming
|
|
72
|
+
if (utterances.has(id) === true) {
|
|
73
|
+
startKeepAlive(id)
|
|
74
|
+
}
|
|
75
|
+
}, 5000)
|
|
76
|
+
}
|
|
49
77
|
}
|
|
50
78
|
|
|
51
79
|
const defaultUtteranceProps = {
|
|
@@ -57,45 +85,124 @@ const defaultUtteranceProps = {
|
|
|
57
85
|
}
|
|
58
86
|
|
|
59
87
|
const initialize = () => {
|
|
88
|
+
// syn api check: syn might not have getVoices method
|
|
89
|
+
if (!syn || typeof syn.getVoices !== 'function') {
|
|
90
|
+
initialized = false
|
|
91
|
+
return
|
|
92
|
+
}
|
|
93
|
+
|
|
60
94
|
const voices = syn.getVoices()
|
|
61
95
|
defaultUtteranceProps.voice = voices[0] || null
|
|
62
96
|
initialized = true
|
|
63
97
|
}
|
|
64
98
|
|
|
65
|
-
const
|
|
66
|
-
|
|
99
|
+
const waitForSynthReady = (timeoutMs = 2000, checkIntervalMs = 100) => {
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
if (!syn) {
|
|
102
|
+
Log.debug('SpeechSynthesis - syn unavailable')
|
|
103
|
+
resolve()
|
|
104
|
+
return
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!syn.speaking && !syn.pending) {
|
|
108
|
+
Log.debug('SpeechSynthesis - ready immediately')
|
|
109
|
+
resolve()
|
|
110
|
+
return
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
Log.debug('SpeechSynthesis - waiting for ready state...')
|
|
114
|
+
|
|
115
|
+
const startTime = Date.now()
|
|
116
|
+
|
|
117
|
+
const intervalId = setInterval(() => {
|
|
118
|
+
const elapsed = Date.now() - startTime
|
|
119
|
+
const isReady = !syn.speaking && !syn.pending
|
|
120
|
+
|
|
121
|
+
if (isReady) {
|
|
122
|
+
Log.debug(`SpeechSynthesis - ready after ${elapsed}ms`)
|
|
123
|
+
clearInterval(intervalId)
|
|
124
|
+
resolve()
|
|
125
|
+
} else if (elapsed >= timeoutMs) {
|
|
126
|
+
Log.debug(`SpeechSynthesis - timeout after ${elapsed}ms, forcing ready`, {
|
|
127
|
+
speaking: syn.speaking,
|
|
128
|
+
pending: syn.pending,
|
|
129
|
+
})
|
|
130
|
+
clearInterval(intervalId)
|
|
131
|
+
resolve()
|
|
132
|
+
}
|
|
133
|
+
}, checkIntervalMs)
|
|
134
|
+
})
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const speak = async (options) => {
|
|
138
|
+
// options check: missing required options
|
|
139
|
+
if (!options || !options.message) {
|
|
140
|
+
return Promise.reject({ error: 'Missing message' })
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// options check: missing or invalid id
|
|
67
144
|
const id = options.id
|
|
145
|
+
if (id === undefined || id === null) {
|
|
146
|
+
return Promise.reject({ error: 'Missing id' })
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// utterance status: utterance with same id already exists
|
|
150
|
+
if (utterances.has(id)) {
|
|
151
|
+
clear(id)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Wait for engine to be ready
|
|
155
|
+
await waitForSynthReady()
|
|
156
|
+
|
|
157
|
+
const utterance = new SpeechSynthesisUtterance(options.message)
|
|
68
158
|
utterance.lang = options.lang || defaultUtteranceProps.lang
|
|
69
159
|
utterance.pitch = options.pitch || defaultUtteranceProps.pitch
|
|
70
160
|
utterance.rate = options.rate || defaultUtteranceProps.rate
|
|
71
161
|
utterance.voice = options.voice || defaultUtteranceProps.voice
|
|
72
162
|
utterance.volume = options.volume || defaultUtteranceProps.volume
|
|
73
|
-
utterances.set(id, utterance) // Strong reference
|
|
74
|
-
|
|
75
|
-
if (isAndroid === false) {
|
|
76
|
-
utterance.onstart = () => {
|
|
77
|
-
resumeInfinity(utterance)
|
|
78
|
-
}
|
|
79
163
|
|
|
80
|
-
|
|
81
|
-
resumeInfinity(utterance)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
164
|
+
utterances.set(id, { utterance, timer: null, ignoreResume: false })
|
|
84
165
|
|
|
85
166
|
return new Promise((resolve, reject) => {
|
|
86
|
-
utterance.onend = () => {
|
|
87
|
-
clear()
|
|
88
|
-
|
|
89
|
-
resolve()
|
|
167
|
+
utterance.onend = (result) => {
|
|
168
|
+
clear(id)
|
|
169
|
+
resolve(result)
|
|
90
170
|
}
|
|
91
171
|
|
|
92
172
|
utterance.onerror = (e) => {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
173
|
+
Log.warn('SpeechSynthesisUtterance error:', e)
|
|
174
|
+
clear(id)
|
|
175
|
+
resolve()
|
|
96
176
|
}
|
|
97
177
|
|
|
98
|
-
|
|
178
|
+
if (options.enableUtteranceKeepAlive === true) {
|
|
179
|
+
utterance.onstart = () => {
|
|
180
|
+
// utterances status: check if utterance still exists
|
|
181
|
+
if (utterances.has(id)) {
|
|
182
|
+
startKeepAlive(id)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
utterance.onresume = () => {
|
|
187
|
+
const state = utterances.get(id)
|
|
188
|
+
// utterance status: utterance might have been removed
|
|
189
|
+
if (!state) return
|
|
190
|
+
|
|
191
|
+
if (state.ignoreResume === true) {
|
|
192
|
+
state.ignoreResume = false
|
|
193
|
+
return
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
startKeepAlive(id)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// handle error: syn.speak might throw
|
|
200
|
+
try {
|
|
201
|
+
syn.speak(utterance)
|
|
202
|
+
} catch (error) {
|
|
203
|
+
clear(id)
|
|
204
|
+
reject(error)
|
|
205
|
+
}
|
|
99
206
|
})
|
|
100
207
|
}
|
|
101
208
|
|
|
@@ -113,8 +220,20 @@ export default {
|
|
|
113
220
|
},
|
|
114
221
|
cancel() {
|
|
115
222
|
if (syn !== undefined) {
|
|
116
|
-
|
|
117
|
-
|
|
223
|
+
// timers: clear all timers before cancelling
|
|
224
|
+
for (const id of utterances.keys()) {
|
|
225
|
+
clear(id)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// handle errors: syn.cancel might throw
|
|
229
|
+
try {
|
|
230
|
+
syn.cancel()
|
|
231
|
+
} catch (error) {
|
|
232
|
+
Log.error('Error cancelling speech synthesis:', error)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// utterances status: ensure all utterances are cleaned up
|
|
236
|
+
utterances.clear()
|
|
118
237
|
}
|
|
119
238
|
},
|
|
120
239
|
// @todo
|
|
@@ -100,6 +100,8 @@ export default {
|
|
|
100
100
|
// pass focus to the parent so we don't get lost in focus limbo
|
|
101
101
|
if (this.$hasFocus === true) this[symbols.parent].$focus()
|
|
102
102
|
|
|
103
|
+
// @todo - is this really necessary?
|
|
104
|
+
// This cause an issue with auto sizing of parent (and required an extra eol check there)
|
|
103
105
|
for (let key in this[symbols.state]) {
|
|
104
106
|
if (Array.isArray(this[symbols.state][key])) {
|
|
105
107
|
this[symbols.state][key] = []
|
|
@@ -108,6 +110,8 @@ export default {
|
|
|
108
110
|
|
|
109
111
|
this.$clearTimeouts()
|
|
110
112
|
this.$clearIntervals()
|
|
113
|
+
this.$clearDebounces()
|
|
114
|
+
|
|
111
115
|
eventListeners.removeListeners(this)
|
|
112
116
|
|
|
113
117
|
const rendererEventListenersLength = this[symbols.rendererEventListeners].length
|
|
@@ -23,6 +23,12 @@ export default {
|
|
|
23
23
|
value: {
|
|
24
24
|
to,
|
|
25
25
|
back,
|
|
26
|
+
get backNavigation() {
|
|
27
|
+
return state.backNavigation !== false
|
|
28
|
+
},
|
|
29
|
+
set backNavigation(enabled) {
|
|
30
|
+
state.backNavigation = enabled !== false
|
|
31
|
+
},
|
|
26
32
|
get currentRoute() {
|
|
27
33
|
return currentRoute
|
|
28
34
|
},
|
|
@@ -96,4 +96,60 @@ export default {
|
|
|
96
96
|
enumerable: true,
|
|
97
97
|
configurable: false,
|
|
98
98
|
},
|
|
99
|
+
$debounce: {
|
|
100
|
+
value: function (name, fn, ms, ...params) {
|
|
101
|
+
// early exit when component is marked as end of life
|
|
102
|
+
if (this.eol === true) return
|
|
103
|
+
|
|
104
|
+
// clear existing debounce for this name if it exists
|
|
105
|
+
const existing = this[symbols.debounces].get(name)
|
|
106
|
+
if (existing !== undefined) {
|
|
107
|
+
this.$clearTimeout(existing)
|
|
108
|
+
this[symbols.debounces].delete(name)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// create new timeout
|
|
112
|
+
const timeoutId = setTimeout(() => {
|
|
113
|
+
this[symbols.debounces].delete(name)
|
|
114
|
+
this.$clearTimeout(timeoutId)
|
|
115
|
+
fn.apply(this, params)
|
|
116
|
+
}, ms)
|
|
117
|
+
|
|
118
|
+
// track timeout in timeouts array for automatic cleanup
|
|
119
|
+
this[symbols.timeouts].push(timeoutId)
|
|
120
|
+
|
|
121
|
+
// store timeoutId per name to enable replace behavior and lifecycle cleanup
|
|
122
|
+
this[symbols.debounces].set(name, timeoutId)
|
|
123
|
+
|
|
124
|
+
return timeoutId
|
|
125
|
+
},
|
|
126
|
+
writable: false,
|
|
127
|
+
enumerable: true,
|
|
128
|
+
configurable: false,
|
|
129
|
+
},
|
|
130
|
+
$clearDebounce: {
|
|
131
|
+
value: function (name) {
|
|
132
|
+
const existing = this[symbols.debounces].get(name)
|
|
133
|
+
if (existing !== undefined) {
|
|
134
|
+
this.$clearTimeout(existing)
|
|
135
|
+
this[symbols.debounces].delete(name)
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
writable: false,
|
|
139
|
+
enumerable: true,
|
|
140
|
+
configurable: false,
|
|
141
|
+
},
|
|
142
|
+
$clearDebounces: {
|
|
143
|
+
value: function () {
|
|
144
|
+
// clear all timeouts associated with debounces
|
|
145
|
+
const timeoutIds = Array.from(this[symbols.debounces].values())
|
|
146
|
+
for (let i = 0; i < timeoutIds.length; i++) {
|
|
147
|
+
this.$clearTimeout(timeoutIds[i])
|
|
148
|
+
}
|
|
149
|
+
this[symbols.debounces].clear()
|
|
150
|
+
},
|
|
151
|
+
writable: false,
|
|
152
|
+
enumerable: true,
|
|
153
|
+
configurable: false,
|
|
154
|
+
},
|
|
99
155
|
}
|
|
@@ -16,12 +16,17 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import symbols from '../../lib/symbols.js'
|
|
19
|
+
import { state as routerState } from '../../router/router.js'
|
|
19
20
|
|
|
20
21
|
export default (component, data) => {
|
|
21
22
|
let routes = data
|
|
22
23
|
if (Array.isArray(data) === false) {
|
|
23
24
|
component[symbols.routerHooks] = data.hooks
|
|
24
25
|
routes = data.routes
|
|
26
|
+
// Set initial backNavigation value if provided in router config
|
|
27
|
+
if (data.backNavigation !== undefined) {
|
|
28
|
+
routerState.backNavigation = data.backNavigation !== false
|
|
29
|
+
}
|
|
25
30
|
}
|
|
26
31
|
component[symbols.routes] = []
|
|
27
32
|
|
package/src/component.js
CHANGED
|
@@ -229,6 +229,9 @@ const Component = (name = required('name'), config = required('config')) => {
|
|
|
229
229
|
// create an empty array for storing intervals created by this component (via this.$setInterval)
|
|
230
230
|
this[symbols.intervals] = []
|
|
231
231
|
|
|
232
|
+
// create a Map for storing debounced functions (via this.$debounce)
|
|
233
|
+
this[symbols.debounces] = new Map()
|
|
234
|
+
|
|
232
235
|
// apply the state function (passing in the this reference to utilize configured props)
|
|
233
236
|
// and store a reference to this original state
|
|
234
237
|
this[symbols.originalState] =
|
|
@@ -361,7 +364,7 @@ const Component = (name = required('name'), config = required('config')) => {
|
|
|
361
364
|
}
|
|
362
365
|
}
|
|
363
366
|
|
|
364
|
-
let old =
|
|
367
|
+
let old = target[key]
|
|
365
368
|
|
|
366
369
|
const eff = (force = false) => {
|
|
367
370
|
const newValue = target[key]
|
|
@@ -456,6 +459,9 @@ const Component = (name = required('name'), config = required('config')) => {
|
|
|
456
459
|
// during the code generation step
|
|
457
460
|
factory[Symbol.for('config')] = config
|
|
458
461
|
|
|
462
|
+
// Display name for inspector
|
|
463
|
+
factory[Symbol.for('componentType')] = name
|
|
464
|
+
|
|
459
465
|
// To determine whether dynamic component is actual Blits component or not
|
|
460
466
|
factory[symbols.isComponent] = true
|
|
461
467
|
|
package/src/components/Circle.js
CHANGED
|
@@ -16,141 +16,157 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import Component from '../component.js'
|
|
19
|
-
import Router from '../router/router.js'
|
|
19
|
+
import Router, { state as routerState } from '../router/router.js'
|
|
20
20
|
import symbols from '../lib/symbols.js'
|
|
21
21
|
import Focus from '../focus.js'
|
|
22
22
|
|
|
23
23
|
let hashchangeHandler = null
|
|
24
24
|
|
|
25
|
+
/** @typedef {{ $input?: (event: any) => boolean, $focus?: (event: any) => void }} RouterViewParent */
|
|
26
|
+
|
|
25
27
|
export default () =>
|
|
26
|
-
Component(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
28
|
+
Component(
|
|
29
|
+
'RouterView',
|
|
30
|
+
/** @type {any} */ ({
|
|
31
|
+
/* eslint-disable no-unused-vars */
|
|
32
|
+
code: {
|
|
33
|
+
render: function anonymous(parent, component, context, components, effect, getRaw, Log) {
|
|
34
|
+
const elms = []
|
|
35
|
+
const validAttributes = [
|
|
36
|
+
'parent',
|
|
37
|
+
'rotation',
|
|
38
|
+
'w',
|
|
39
|
+
'width',
|
|
40
|
+
'h',
|
|
41
|
+
'height',
|
|
42
|
+
'x',
|
|
43
|
+
'y',
|
|
44
|
+
'z',
|
|
45
|
+
'zIndex',
|
|
46
|
+
'color',
|
|
47
|
+
'src',
|
|
48
|
+
'texture',
|
|
49
|
+
'fit',
|
|
50
|
+
'rtt',
|
|
51
|
+
'mount',
|
|
52
|
+
'pivot',
|
|
53
|
+
'scale',
|
|
54
|
+
'show',
|
|
55
|
+
'alpha',
|
|
56
|
+
'rounded',
|
|
57
|
+
'border',
|
|
58
|
+
'shadow',
|
|
59
|
+
'shader',
|
|
60
|
+
'clipping',
|
|
61
|
+
'overflow',
|
|
62
|
+
'font',
|
|
63
|
+
'size',
|
|
64
|
+
'maxwidth',
|
|
65
|
+
'maxheight',
|
|
66
|
+
'maxlines',
|
|
67
|
+
'textoverflow',
|
|
68
|
+
'letterspacing',
|
|
69
|
+
'lineheight',
|
|
70
|
+
'contain',
|
|
71
|
+
'align',
|
|
72
|
+
'content',
|
|
73
|
+
'placement',
|
|
74
|
+
'inspector-data',
|
|
75
|
+
]
|
|
76
|
+
const elementConfigs = []
|
|
77
|
+
const forloops = []
|
|
78
|
+
const props = []
|
|
79
|
+
const created = []
|
|
80
|
+
const effects = {}
|
|
81
|
+
const skips = []
|
|
82
|
+
let componentType
|
|
83
|
+
let rootComponent = component
|
|
84
|
+
let propData
|
|
85
|
+
let slotComponent
|
|
86
|
+
let inSlot = false
|
|
87
|
+
let slotChildCounter = 0
|
|
88
|
+
let cmps = []
|
|
89
|
+
elementConfigs[0] = {}
|
|
90
|
+
elementConfigs[0]['___wrapper'] = true
|
|
86
91
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
92
|
+
elms[0] = this.element(
|
|
93
|
+
{ parent: parent || 'root' },
|
|
94
|
+
inSlot === true ? slotComponent : component
|
|
95
|
+
)
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
elementConfigs[0]['w'] = parent.node.w * (100 / 100)
|
|
98
|
+
elementConfigs[0]['height'] = parent.node.h * (100 / 100)
|
|
99
|
+
elms[0].populate(elementConfigs[0])
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
if (inSlot === true) {
|
|
102
|
+
slotChildCounter -= 1
|
|
103
|
+
}
|
|
99
104
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
105
|
+
return {
|
|
106
|
+
elms,
|
|
107
|
+
cleanup: () => {
|
|
108
|
+
rootComponent = null
|
|
109
|
+
propData = null
|
|
110
|
+
slotComponent = null
|
|
111
|
+
parent = null
|
|
112
|
+
component = null
|
|
113
|
+
cmps.length = 0
|
|
114
|
+
elms.length = 0
|
|
115
|
+
components.length = 0
|
|
116
|
+
elementConfigs.length = 0
|
|
117
|
+
forloops.length = 0
|
|
118
|
+
props.length = 0
|
|
119
|
+
skips.length = 0
|
|
120
|
+
},
|
|
121
|
+
skips,
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
effects: [],
|
|
125
|
+
context: {},
|
|
118
126
|
},
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
state() {
|
|
123
|
-
return {
|
|
124
|
-
activeView: null,
|
|
125
|
-
}
|
|
126
|
-
},
|
|
127
|
-
hooks: {
|
|
128
|
-
async ready() {
|
|
129
|
-
if (
|
|
130
|
-
this[symbols.parent][symbols.routerHooks] &&
|
|
131
|
-
this[symbols.parent][symbols.routerHooks].init
|
|
132
|
-
) {
|
|
133
|
-
await this[symbols.parent][symbols.routerHooks].init.apply(this[symbols.parent])
|
|
127
|
+
state() {
|
|
128
|
+
return {
|
|
129
|
+
activeView: null,
|
|
134
130
|
}
|
|
135
|
-
hashchangeHandler = () => Router.navigate.apply(this)
|
|
136
|
-
Router.navigate.apply(this)
|
|
137
|
-
window.addEventListener('hashchange', hashchangeHandler)
|
|
138
|
-
},
|
|
139
|
-
destroy() {
|
|
140
|
-
window.removeEventListener('hashchange', hashchangeHandler, false)
|
|
141
131
|
},
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
this.
|
|
145
|
-
|
|
132
|
+
hooks: {
|
|
133
|
+
async ready() {
|
|
134
|
+
const parent = this[symbols.parent]
|
|
135
|
+
if (parent && parent[symbols.routerHooks] && parent[symbols.routerHooks].init) {
|
|
136
|
+
await parent[symbols.routerHooks].init.apply(parent)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
hashchangeHandler = () => Router.navigate.apply(this)
|
|
140
|
+
Router.navigate.apply(this)
|
|
141
|
+
window.addEventListener('hashchange', hashchangeHandler)
|
|
142
|
+
},
|
|
143
|
+
destroy() {
|
|
144
|
+
window.removeEventListener('hashchange', hashchangeHandler, false)
|
|
145
|
+
},
|
|
146
|
+
focus() {
|
|
147
|
+
if (this.activeView && Focus.get() === this) {
|
|
148
|
+
this.activeView.$focus()
|
|
149
|
+
}
|
|
150
|
+
},
|
|
146
151
|
},
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
input: {
|
|
153
|
+
back(e) {
|
|
154
|
+
const parent = this[symbols.parent]
|
|
155
|
+
|
|
156
|
+
if (routerState.backNavigation === false) {
|
|
157
|
+
if (parent && parent.$input) {
|
|
158
|
+
parent.$input(e)
|
|
159
|
+
}
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const navigating = Router.back.call(this)
|
|
164
|
+
if (navigating === false) {
|
|
165
|
+
if (parent && parent.$focus) {
|
|
166
|
+
parent.$focus(e)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
},
|
|
154
170
|
},
|
|
155
|
-
}
|
|
156
|
-
|
|
171
|
+
})
|
|
172
|
+
)
|