@lightningjs/blits 0.3.15 → 0.4.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.
@@ -17,25 +17,27 @@
17
17
 
18
18
  import { Log } from '../log.js'
19
19
 
20
+ import symbols from '../symbols.js'
21
+
20
22
  export default (component, state) => {
21
- component.___stateKeys = []
23
+ component[symbols.stateKeys] = []
22
24
 
23
25
  state = state.apply(component.prototype)
24
26
  Object.keys(state).forEach((key) => {
25
- if (component.___propKeys && component.___propKeys.indexOf(key) > -1) {
27
+ if (component[symbols.propKeys] && component[symbols.propKeys].indexOf(key) > -1) {
26
28
  Log.error(`State ${key} already exists as a prop`)
27
29
  }
28
- if (component.___methodKeys && component.___methodKeys.indexOf(key) > -1) {
30
+ if (component[symbols.methodKeys] && component[symbols.methodKeys].indexOf(key) > -1) {
29
31
  Log.error(`State ${key} already exists as a method`)
30
32
  }
31
- component.___stateKeys.push(key)
33
+ component[symbols.stateKeys].push(key)
32
34
  try {
33
35
  Object.defineProperty(component.prototype, key, {
34
36
  get() {
35
- return this.___state && key in this.___state && this.___state[key]
37
+ return this[symbols.state] && key in this[symbols.state] && this[symbols.state][key]
36
38
  },
37
39
  set(v) {
38
- if (this.___state) this.___state[key] = v
40
+ if (this[symbols.state]) this[symbols.state][key] = v
39
41
  },
40
42
  })
41
43
  } catch (e) {
@@ -15,18 +15,20 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
+ import symbols from '../symbols.js'
19
+
18
20
  export default (component, watchers) => {
19
- component.prototype.___watchKeys = []
20
- component.prototype.___watchers = {}
21
+ component.prototype[symbols.watchKeys] = []
22
+ component.prototype[symbols.watchers] = {}
21
23
 
22
24
  for (let watch in watchers) {
23
25
  if (typeof watchers[watch] !== 'function') {
24
26
  console.warn(`${watch} is not a function`)
25
27
  }
26
28
 
27
- component.prototype.___watchKeys.push(watch)
29
+ component.prototype[symbols.watchKeys].push(watch)
28
30
 
29
- component.prototype.___watchers[watch] = function (v, old) {
31
+ component.prototype[symbols.watchers][watch] = function (v, old) {
30
32
  watchers[watch].call(this, v, old)
31
33
  }
32
34
  }
@@ -0,0 +1,41 @@
1
+ export default {
2
+ currentView: Symbol('currentView'),
3
+ computedKeys: Symbol('computedKeys'),
4
+ destroy: Symbol('destroy'),
5
+ index: Symbol('index'),
6
+ init: Symbol('init'),
7
+ inputEvents: Symbol('inputEvents'),
8
+ intervals: Symbol('intervals'),
9
+ _intervals: Symbol('_intervals'),
10
+ level: Symbol('level'),
11
+ methodKeys: Symbol('methodKeys'),
12
+ originalState: Symbol('originalState'),
13
+ propKeys: Symbol('propKeys'),
14
+ ready: Symbol('ready'),
15
+ renderer: Symbol('renderer'),
16
+ routes: Symbol('routes'),
17
+ settings: Symbol('settings'),
18
+ state: Symbol('state'),
19
+ stateKeys: Symbol('stateKeys'),
20
+ textnode: Symbol('textnode'),
21
+ timeouts: Symbol('timeouts'),
22
+ _timeouts: Symbol('_timeouts'),
23
+ type: Symbol('type'),
24
+ watchers: Symbol('watchers'),
25
+ watchKeys: Symbol('watchKeys'),
26
+
27
+ /* Utilizing the global Symbol registry for the following purposes */
28
+
29
+ // Symbol 'children' utilized within generated code
30
+ children: Symbol.for('children'),
31
+ // Symbol 'components' utilized within generated code
32
+ components: Symbol.for('components'),
33
+ // Symbol 'id' utilized within generated code
34
+ id: Symbol.for('id'),
35
+ // Symbol 'isSlot' utilized within generated code
36
+ isSlot: Symbol.for('isSlot'),
37
+ // Symbol 'props' utilized within generated code
38
+ props: Symbol.for('props'),
39
+ // Symbol 'slots' utilized within generated code
40
+ slots: Symbol.for('slots'),
41
+ }
@@ -15,6 +15,8 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
+ import symbols from '../symbols.js'
19
+
18
20
  class TemplateParseError extends Error {
19
21
  constructor(message, name, context) {
20
22
  super(`TemplateParseError ${message}`)
@@ -82,7 +84,7 @@ export default (template = '') => {
82
84
  const parseEmptyTagStart = () => {
83
85
  const match = moveCursorOnMatch(emptyTagStartRegex)
84
86
  if (match) {
85
- tags.push({ type: null, __type: 'opening', __level: currentLevel })
87
+ tags.push({ type: null, [symbols.type]: 'opening', [symbols.level]: currentLevel })
86
88
  currentLevel++
87
89
  parseLoop(parseEmptyTagStart)
88
90
  } else {
@@ -94,7 +96,7 @@ export default (template = '') => {
94
96
  const match = moveCursorOnMatch(emptyTagEndRegex)
95
97
  if (match) {
96
98
  currentLevel--
97
- tags.push({ type: null, __type: 'closing', __level: currentLevel })
99
+ tags.push({ type: null, [symbols.type]: 'closing', [symbols.level]: currentLevel })
98
100
  parseLoop(parseEmptyTagStart)
99
101
  } else {
100
102
  parseLoop(parseTag)
@@ -106,9 +108,9 @@ export default (template = '') => {
106
108
  if (match) {
107
109
  if (match[0].startsWith('</')) {
108
110
  currentLevel--
109
- currentTag = { type: match[1], __type: 'closing', __level: currentLevel }
111
+ currentTag = { type: match[1], [symbols.type]: 'closing', [symbols.level]: currentLevel }
110
112
  } else {
111
- currentTag = { type: match[1], __type: 'opening', __level: currentLevel }
113
+ currentTag = { type: match[1], [symbols.type]: 'opening', [symbols.level]: currentLevel }
112
114
  currentLevel++
113
115
  }
114
116
  parseLoop(parseTagEnd)
@@ -121,13 +123,13 @@ export default (template = '') => {
121
123
  const match = moveCursorOnMatch(tagEndRegex)
122
124
  if (match) {
123
125
  if (match[1] === '/>') {
124
- currentTag.__type = 'self-closing'
126
+ currentTag[symbols.type] = 'self-closing'
125
127
  currentLevel-- // because it was parsed as opening tag before
126
128
  }
127
129
 
128
130
  // parsing content in between tags
129
131
  // rule: < char cannot be used in between tags even in escaped form
130
- if (currentTag.__type === 'opening') {
132
+ if (currentTag[symbols.type] === 'opening') {
131
133
  const tagContent = template.slice(cursor, template.indexOf('<', cursor))
132
134
  if (tagContent) {
133
135
  currentTag.content = tagContent
@@ -178,12 +180,12 @@ export default (template = '') => {
178
180
  let output = { children: [] }
179
181
 
180
182
  for (const item of data) {
181
- const { type, __type, __level } = item
183
+ const { type, [symbols.type]: __type, [symbols.level]: __level } = item
182
184
 
183
185
  // Check for unclosed tags
184
- while (stack.length && stack[stack.length - 1].__level >= __level) {
186
+ while (stack.length && stack[stack.length - 1][symbols.level] >= __level) {
185
187
  const popped = stack.pop()
186
- if (popped.__type === 'opening') {
188
+ if (popped[symbols.type] === 'opening') {
187
189
  throw new TemplateParseError('MismatchedClosingTag', `tag: ${popped.type || 'null'}`)
188
190
  }
189
191
  }
@@ -206,8 +208,8 @@ export default (template = '') => {
206
208
 
207
209
  // Create a new item, copying properties but deleting __type and __level
208
210
  const newItem = { ...item }
209
- delete newItem.__type
210
- delete newItem.__level
211
+ delete newItem[symbols.type]
212
+ delete newItem[symbols.level]
211
213
 
212
214
  if (__type === 'opening') {
213
215
  newItem.children = []
@@ -0,0 +1,166 @@
1
+ /*
2
+ * Copyright 2023 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
+
18
+ import { default as fadeInFadeOutTransition } from './transitions/fadeInOut.js'
19
+
20
+ import symbols from '../lib/symbols.js'
21
+ import { Log } from '../lib/log.js'
22
+ import Element from '../element.js'
23
+ import Focus from '../focus.js'
24
+
25
+ export let currentRoute
26
+ export let navigating = false
27
+
28
+ const cacheMap = new WeakMap()
29
+
30
+ export const getHash = () => {
31
+ return (document.location.hash || '/').replace(/^#/, '')
32
+ }
33
+
34
+ export const matchHash = (path, routes = []) => {
35
+ const route = routes
36
+ .filter((r) => {
37
+ return r.path === path
38
+ })
39
+ .pop()
40
+ if (route) currentRoute = route
41
+ return route
42
+ }
43
+
44
+ export const navigate = async function () {
45
+ navigating = true
46
+ if (this.parent[symbols.routes]) {
47
+ const previousRoute = currentRoute
48
+ const hash = getHash()
49
+ const route = matchHash(hash, this.parent[symbols.routes])
50
+
51
+ if (route) {
52
+ // apply default transition if none specified
53
+ if (!('transition' in route)) {
54
+ route.transition = fadeInFadeOutTransition
55
+ }
56
+ // a transition can be a function returning a dynamic transition object
57
+ // based on current and previous route
58
+ if (typeof route.transition === 'function') {
59
+ route.transition = route.transition(previousRoute, route)
60
+ }
61
+
62
+ let holder
63
+ let { view, focus } = cacheMap.get(route) || {}
64
+
65
+ if (!view) {
66
+ // create a holder element for the new view
67
+ holder = Element({ parent: this[symbols.children][0] })
68
+ holder.populate({})
69
+ holder.set('w', '100%')
70
+ holder.set('h', '100%')
71
+ view = route.component(this[symbols.props], holder, this)
72
+ } else {
73
+ holder = view.wrapper
74
+ }
75
+
76
+ this[symbols.children].push(view)
77
+
78
+ // apply before settings to holder element
79
+ if (route.transition.before) {
80
+ if (Array.isArray(route.transition.before)) {
81
+ for (let i = 0; i < route.transition.before.length; i++) {
82
+ holder.set(route.transition.before[i].prop, route.transition.before[i].value)
83
+ }
84
+ } else {
85
+ holder.set(route.transition.before.prop, route.transition.before.value)
86
+ }
87
+ }
88
+
89
+ let shouldAnimate = false
90
+
91
+ // apply out out transition on previous view
92
+ if (previousRoute) {
93
+ // only animate when there is a previous route
94
+ shouldAnimate = true
95
+ const oldView = this[symbols.children].splice(1, 1).pop()
96
+ if (oldView) {
97
+ removeView(previousRoute, oldView, route.transition.out)
98
+ }
99
+ }
100
+
101
+ // apply in transition
102
+ if (route.transition.in) {
103
+ if (Array.isArray(route.transition.in)) {
104
+ for (let i = 0; i < route.transition.in.length; i++) {
105
+ i === route.transition.length - 1
106
+ ? await setOrAnimate(holder, route.transition.in[i], shouldAnimate)
107
+ : setOrAnimate(holder, route.transition.in[i], shouldAnimate)
108
+ }
109
+ } else {
110
+ await setOrAnimate(holder, route.transition.in, shouldAnimate)
111
+ }
112
+ }
113
+
114
+ // focus the new view
115
+ focus ? Focus.set(focus) : view.focus()
116
+ } else {
117
+ Log.error(`Route ${hash} not found`)
118
+ }
119
+ }
120
+ navigating = false
121
+ }
122
+
123
+ const removeView = async (route, view, transition) => {
124
+ // apply out transition
125
+ if (transition) {
126
+ if (Array.isArray(transition)) {
127
+ for (let i = 0; i < transition.length; i++) {
128
+ i === transition.length - 1
129
+ ? await setOrAnimate(view.wrapper, transition[i])
130
+ : setOrAnimate(view.wrapper, transition[i])
131
+ }
132
+ } else {
133
+ await setOrAnimate(view.wrapper, transition)
134
+ }
135
+ }
136
+
137
+ // cache the page when it's as 'keepAlive' instead of destroying
138
+ if (route.options && route.options.keepAlive === true) {
139
+ cacheMap.set(route, { view: view, focus: Focus.get() })
140
+ } else {
141
+ // remove and cleanup
142
+ for (let i = 0; i < view[symbols.children].length - 1; i++) {
143
+ if (view[symbols.children][i] && view[symbols.children][i].destroy) {
144
+ view[symbols.children][i].destroy()
145
+ view[symbols.children][i] = null
146
+ }
147
+ }
148
+ view.destroy()
149
+ view = null
150
+ }
151
+ }
152
+
153
+ const setOrAnimate = (node, transition, shouldAnimate = true) => {
154
+ return shouldAnimate
155
+ ? node.animate(transition.prop, transition)
156
+ : node.set(transition.prop, transition.value)
157
+ }
158
+
159
+ export const to = (location) => {
160
+ window.location.hash = `#${location}`
161
+ }
162
+
163
+ export default {
164
+ navigate,
165
+ to,
166
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * Copyright 2023 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
+
18
+ export default {
19
+ before: {
20
+ prop: 'alpha',
21
+ value: 0,
22
+ },
23
+ in: {
24
+ prop: 'alpha',
25
+ value: 1,
26
+ },
27
+ }
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Copyright 2023 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
+
18
+ export default {
19
+ before: {
20
+ prop: 'alpha',
21
+ value: 0,
22
+ },
23
+ in: {
24
+ prop: 'alpha',
25
+ value: 1,
26
+ duration: 200,
27
+ },
28
+ out: {
29
+ prop: 'alpha',
30
+ value: 0,
31
+ duration: 100,
32
+ },
33
+ }
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Copyright 2023 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
+
18
+ export { default as fadeIn } from './fadeIn.js'
19
+ export { default as fadeInOut } from './fadeInOut.js'
20
+ export { default as slideIn } from './slideIn.js'
21
+ export { default as slideInOut } from './slideInOut.js'
@@ -0,0 +1,28 @@
1
+ /*
2
+ * Copyright 2023 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
+
18
+ export default {
19
+ before: {
20
+ prop: 'x',
21
+ value: '-100%',
22
+ },
23
+ in: {
24
+ prop: 'x',
25
+ value: 0,
26
+ duration: 200,
27
+ },
28
+ }
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Copyright 2023 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
+
18
+ export default {
19
+ before: {
20
+ prop: 'x',
21
+ value: '-100%',
22
+ },
23
+ in: {
24
+ prop: 'x',
25
+ value: 0,
26
+ duration: 200,
27
+ },
28
+ out: {
29
+ prop: 'x',
30
+ value: '100%',
31
+ duration: 200,
32
+ },
33
+ }
package/src/router.js CHANGED
@@ -17,6 +17,8 @@
17
17
 
18
18
  import { Log } from './lib/log.js'
19
19
 
20
+ import symbols from './lib/symbols.js'
21
+
20
22
  export const getHash = () => {
21
23
  return (document.location.hash || '/').replace(/^#/, '')
22
24
  }
@@ -31,26 +33,29 @@ export const matchHash = (path, routes = []) => {
31
33
  }
32
34
 
33
35
  export const navigate = function () {
34
- if (this.parent.___routes) {
36
+ if (this.parent[symbols.routes]) {
35
37
  const hash = getHash()
36
- const route = matchHash(hash, this.parent.___routes)
38
+ const route = matchHash(hash, this.parent[symbols.routes])
37
39
  if (route) {
38
- if (this.__currentView) {
39
- for (let i = 0; i < this.__currentView.___children.length - 1; i++) {
40
- if (this.__currentView.___children[i] && this.__currentView.___children[i].destroy) {
41
- this.__currentView.___children[i].destroy()
42
- this.__currentView.___children[i] = null
40
+ if (this[symbols.currentView]) {
41
+ for (let i = 0; i < this[symbols.currentView][symbols.children].length - 1; i++) {
42
+ if (
43
+ this[symbols.currentView][symbols.children][i] &&
44
+ this[symbols.currentView][symbols.children][i].destroy
45
+ ) {
46
+ this[symbols.currentView][symbols.children][i].destroy()
47
+ this[symbols.currentView][symbols.children][i] = null
43
48
  }
44
49
  }
45
- this.__currentView.destroy()
46
- this.__currentView = null
50
+ this[symbols.currentView].destroy()
51
+ this[symbols.currentView] = null
47
52
  }
48
- this.___children[1] = this.__currentView = route.component(
49
- this.___props,
50
- this.___children[0],
53
+ this[symbols.children][1] = this[symbols.currentView] = route.component(
54
+ this[symbols.props],
55
+ this[symbols.children][0],
51
56
  this
52
57
  )
53
- this.__currentView.focus()
58
+ this[symbols.currentView].focus()
54
59
  } else {
55
60
  Log.error(`Route ${hash} not found`)
56
61
  }
package/src/settings.js CHANGED
@@ -15,10 +15,16 @@
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
 
18
+ import symbols from './lib/symbols.js'
19
+
18
20
  const settings = {
19
- ___settings: {},
21
+ [symbols.settings]: {},
20
22
  get(key, defaultValue = null) {
21
- return (key in this.___settings && this.___settings[key]) || defaultValue
23
+ if (key in this[symbols.settings]) {
24
+ return this[symbols.settings][key]
25
+ } else {
26
+ return defaultValue
27
+ }
22
28
  },
23
29
  set(key, value) {
24
30
  if (typeof key === 'object') {
@@ -26,7 +32,7 @@ const settings = {
26
32
  this.set(k, key[k])
27
33
  })
28
34
  } else {
29
- this.___settings[key] = value
35
+ this[symbols.settings][key] = value
30
36
  }
31
37
  },
32
38
  }
File without changes