@lightningjs/blits 1.6.1 → 1.7.1
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 +14 -1
- package/bin/index.js +0 -0
- package/docs/components/user_input.md +4 -4
- package/package.json +1 -1
- package/src/component/base/methods.js +2 -0
- package/src/component/setup/index.js +2 -0
- package/src/component.js +5 -2
- package/src/lib/codegenerator/generator.js +5 -3
- package/src/lib/reactivity/effect.js +17 -1
- package/src/lib/reactivity/reactive.js +10 -8
- package/src/lib/symbols.js +2 -0
- package/src/plugins/appstate.js +1 -1
- package/src/plugins/language.js +2 -1
- package/src/plugins/theme.js +2 -1
- package/vite/msdfGenerator.js +24 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## v1.
|
|
3
|
+
## v1.7.1
|
|
4
|
+
|
|
5
|
+
_14 oct 2024_
|
|
6
|
+
|
|
7
|
+
- Fixed support for `.otf` and `.woff` fonts files in combination with MSDF generator
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## v1.7.0
|
|
11
|
+
|
|
12
|
+
_14 oct 2024_
|
|
13
|
+
|
|
14
|
+
- Added cleanup upon component destroy of effects generated by global reactivity
|
|
15
|
+
|
|
16
|
+
## v1.6.0 / v1.6.1
|
|
4
17
|
|
|
5
18
|
_9 oct 2024_
|
|
6
19
|
|
package/bin/index.js
CHANGED
|
File without changes
|
|
@@ -125,9 +125,9 @@ Blits comes with a default keycode mapping. This mapping is a sensible default t
|
|
|
125
125
|
|
|
126
126
|
But it's possible that the keycodes and mapping of your target device are slightly or even completely different.
|
|
127
127
|
|
|
128
|
-
In Blits, you can easily configure the key mapping to match your needs. In the `src/index.js` file where we instantiate the App via the `Blits.Launch` function, we can add an extra key, called `
|
|
128
|
+
In Blits, you can easily configure the key mapping to match your needs. In the `src/index.js` file where we instantiate the App via the `Blits.Launch` function, we can add an extra key, called `keymap`, to the _settings object_.
|
|
129
129
|
|
|
130
|
-
The `
|
|
130
|
+
The `keymap` should contain an object literal, where you map a `key` or `keyCode` (from the `KeyboardEvent`) to an event name that you can use in your Components.
|
|
131
131
|
|
|
132
132
|
> You can use a site like [keyjs.dev](https://keyjs.dev/) to find the appropriate key and keyCode for your device
|
|
133
133
|
|
|
@@ -137,7 +137,7 @@ Blits.Launch(App, 'app', {
|
|
|
137
137
|
w: 1920,
|
|
138
138
|
h: 1080,
|
|
139
139
|
//...
|
|
140
|
-
|
|
140
|
+
keymap: {
|
|
141
141
|
// switch left and right using the key
|
|
142
142
|
ArrowLeft: 'right',
|
|
143
143
|
ArrowRight: 'left',
|
|
@@ -152,7 +152,7 @@ Blits.Launch(App, 'app', {
|
|
|
152
152
|
})
|
|
153
153
|
```
|
|
154
154
|
|
|
155
|
-
The custom
|
|
155
|
+
The custom keymap object will be merged with the default key mapping, that looks like this:
|
|
156
156
|
|
|
157
157
|
```js
|
|
158
158
|
const defaultKeyMap = {
|
package/package.json
CHANGED
|
@@ -20,6 +20,7 @@ import Focus from '../../focus.js'
|
|
|
20
20
|
import eventListeners from '../../lib/eventListeners.js'
|
|
21
21
|
import { trigger } from '../../lib/reactivity/effect.js'
|
|
22
22
|
import { Log } from '../../lib/log.js'
|
|
23
|
+
import { removeGlobalEffects } from '../../lib/reactivity/effect.js'
|
|
23
24
|
|
|
24
25
|
export default {
|
|
25
26
|
focus: {
|
|
@@ -56,6 +57,7 @@ export default {
|
|
|
56
57
|
this.$clearIntervals()
|
|
57
58
|
eventListeners.removeListeners(this)
|
|
58
59
|
deleteChildren(this[symbols.children])
|
|
60
|
+
removeGlobalEffects(this[symbols.effects])
|
|
59
61
|
Log.debug(`Destroyed component ${this.componentId}`)
|
|
60
62
|
},
|
|
61
63
|
writable: false,
|
package/src/component.js
CHANGED
|
@@ -161,9 +161,12 @@ const Component = (name = required('name'), config = required('config')) => {
|
|
|
161
161
|
// reactive bindings define in the template
|
|
162
162
|
const effects = config.code.effects
|
|
163
163
|
for (let i = 0; i < effects.length; i++) {
|
|
164
|
-
|
|
164
|
+
const eff = () => {
|
|
165
165
|
effects[i](this, this[symbols.children], config, globalComponents, rootComponent, effect)
|
|
166
|
-
}
|
|
166
|
+
}
|
|
167
|
+
// store reference to the effect
|
|
168
|
+
this[symbols.effects].push(eff)
|
|
169
|
+
effect(eff)
|
|
167
170
|
}
|
|
168
171
|
|
|
169
172
|
// setup watchers if the components has watchers specified
|
|
@@ -392,13 +392,15 @@ const generateForLoopCode = function (templateObject, parent) {
|
|
|
392
392
|
}
|
|
393
393
|
|
|
394
394
|
// inner scope variables are part of the main forloop
|
|
395
|
-
innerScopeEffects.forEach((effect) => {
|
|
395
|
+
innerScopeEffects.forEach((effect, index) => {
|
|
396
396
|
const key = effect.indexOf(`scope.${index}`) > -1 ? `'${interpolate(result[2], '')}'` : null
|
|
397
397
|
if (effect.indexOf("Symbol.for('props')") === -1) {
|
|
398
398
|
ctx.renderCode.push(`
|
|
399
|
-
|
|
399
|
+
let eff${index} = () => {
|
|
400
400
|
${effect}
|
|
401
|
-
}
|
|
401
|
+
}
|
|
402
|
+
effect(eff${index}, ${key})
|
|
403
|
+
component[Symbol.for('effects')].push(eff${index})
|
|
402
404
|
`)
|
|
403
405
|
} else {
|
|
404
406
|
// props shouldn't be wrapped in an effect, but simply passed on
|
|
@@ -29,8 +29,22 @@ export const resumeTracking = () => {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const objectMap = new WeakMap()
|
|
32
|
+
const globalEffectsMap = new Map()
|
|
32
33
|
|
|
33
|
-
export const
|
|
34
|
+
export const removeGlobalEffects = (effectsToRemove) => {
|
|
35
|
+
if (globalEffectsMap.size === 0) return
|
|
36
|
+
for (const [effect, target] of globalEffectsMap) {
|
|
37
|
+
if (effectsToRemove.indexOf(effect) === -1) continue
|
|
38
|
+
const effectsSet = objectMap.get(target)
|
|
39
|
+
if (effectsSet === undefined) continue
|
|
40
|
+
for (const set of effectsSet.values()) {
|
|
41
|
+
set.delete(effect)
|
|
42
|
+
globalEffectsMap.delete(effect)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const track = (target, key, global = false) => {
|
|
34
48
|
if (currentEffect) {
|
|
35
49
|
if (paused) {
|
|
36
50
|
return
|
|
@@ -49,6 +63,8 @@ export const track = (target, key) => {
|
|
|
49
63
|
effectsMap.set(key, effects)
|
|
50
64
|
}
|
|
51
65
|
effects.add(currentEffect)
|
|
66
|
+
|
|
67
|
+
if (global === true) globalEffectsMap.set(currentEffect, target)
|
|
52
68
|
}
|
|
53
69
|
}
|
|
54
70
|
|
|
@@ -28,7 +28,7 @@ export const getRaw = (value) => {
|
|
|
28
28
|
return raw ? getRaw(raw) : value
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
const reactiveProxy = (original, _parent = null, _key) => {
|
|
31
|
+
const reactiveProxy = (original, _parent = null, _key, global) => {
|
|
32
32
|
// don't create a proxy when a Blits component or an Image Texture
|
|
33
33
|
// is assigned to a state variable
|
|
34
34
|
if (typeof original === 'object') {
|
|
@@ -53,7 +53,7 @@ const reactiveProxy = (original, _parent = null, _key) => {
|
|
|
53
53
|
if (Array.isArray(target)) {
|
|
54
54
|
if (typeof target[key] === 'object' && target[key] !== null) {
|
|
55
55
|
if (Array.isArray(target[key])) {
|
|
56
|
-
track(target, key)
|
|
56
|
+
track(target, key, global)
|
|
57
57
|
}
|
|
58
58
|
// create a new reactive proxy
|
|
59
59
|
return reactiveProxy(getRaw(target[key]), target, key)
|
|
@@ -81,7 +81,7 @@ const reactiveProxy = (original, _parent = null, _key) => {
|
|
|
81
81
|
// handling objects (but not null values, which have object type in JS)
|
|
82
82
|
if (typeof target[key] === 'object' && target[key] !== null) {
|
|
83
83
|
if (Array.isArray(target[key])) {
|
|
84
|
-
track(target, key)
|
|
84
|
+
track(target, key, global)
|
|
85
85
|
}
|
|
86
86
|
// create a new reactive proxy
|
|
87
87
|
return reactiveProxy(getRaw(target[key]), target, key)
|
|
@@ -89,7 +89,7 @@ const reactiveProxy = (original, _parent = null, _key) => {
|
|
|
89
89
|
|
|
90
90
|
// handling all other types
|
|
91
91
|
// track the key on the target
|
|
92
|
-
track(target, key)
|
|
92
|
+
track(target, key, global)
|
|
93
93
|
// return the reflected value
|
|
94
94
|
return Reflect.get(target, key, receiver)
|
|
95
95
|
},
|
|
@@ -119,7 +119,7 @@ const reactiveProxy = (original, _parent = null, _key) => {
|
|
|
119
119
|
return proxy
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
const reactiveDefineProperty = (target) => {
|
|
122
|
+
const reactiveDefineProperty = (target, global) => {
|
|
123
123
|
Object.keys(target).forEach((key) => {
|
|
124
124
|
let internalValue = target[key]
|
|
125
125
|
|
|
@@ -140,7 +140,7 @@ const reactiveDefineProperty = (target) => {
|
|
|
140
140
|
enumerable: true,
|
|
141
141
|
configurable: true,
|
|
142
142
|
get() {
|
|
143
|
-
track(target, key)
|
|
143
|
+
track(target, key, global)
|
|
144
144
|
return internalValue
|
|
145
145
|
},
|
|
146
146
|
set(newValue) {
|
|
@@ -157,8 +157,10 @@ const reactiveDefineProperty = (target) => {
|
|
|
157
157
|
return target
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
export const reactive = (target, mode = 'Proxy') => {
|
|
161
|
-
return mode === 'defineProperty'
|
|
160
|
+
export const reactive = (target, mode = 'Proxy', global = false) => {
|
|
161
|
+
return mode === 'defineProperty'
|
|
162
|
+
? reactiveDefineProperty(target, global)
|
|
163
|
+
: reactiveProxy(target, undefined, undefined, global)
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
export const memo = (raw) => {
|
package/src/lib/symbols.js
CHANGED
package/src/plugins/appstate.js
CHANGED
package/src/plugins/language.js
CHANGED
package/src/plugins/theme.js
CHANGED
package/vite/msdfGenerator.js
CHANGED
|
@@ -49,9 +49,19 @@ export default function () {
|
|
|
49
49
|
if (!fs.existsSync(path.resolve(fontDir, file))) {
|
|
50
50
|
const fontName = match[1]
|
|
51
51
|
const ext = match[2]
|
|
52
|
-
const fontFile = path.join(fontDir, `${fontName}.ttf`)
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
// Attempt to find the font file with supported extensions
|
|
54
|
+
const supportedExtensions = ['ttf', 'otf', 'woff']
|
|
55
|
+
let fontFile = null
|
|
56
|
+
for (const fontExt of supportedExtensions) {
|
|
57
|
+
const potentialPath = path.join(fontDir, `${fontName}.${fontExt}`)
|
|
58
|
+
if (fs.existsSync(potentialPath)) {
|
|
59
|
+
fontFile = potentialPath
|
|
60
|
+
break
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (fontFile) {
|
|
55
65
|
const generatedFontFile = path.join(
|
|
56
66
|
msdfOutputDir,
|
|
57
67
|
fontPath,
|
|
@@ -83,7 +93,7 @@ export default function () {
|
|
|
83
93
|
next() // Handle case where generation might have failed
|
|
84
94
|
}
|
|
85
95
|
} else {
|
|
86
|
-
next() //
|
|
96
|
+
next() // No supported font file found
|
|
87
97
|
}
|
|
88
98
|
} else {
|
|
89
99
|
next() // file exists
|
|
@@ -95,18 +105,18 @@ export default function () {
|
|
|
95
105
|
},
|
|
96
106
|
// after build ends, the first hook is renderStart where we can modify the output
|
|
97
107
|
async renderStart() {
|
|
98
|
-
const
|
|
108
|
+
const fontFiles = findAllFontFiles(publicDir)
|
|
99
109
|
|
|
100
|
-
for (const
|
|
101
|
-
const relativePath = path.relative(publicDir, path.dirname(
|
|
102
|
-
const baseName = path.basename(
|
|
110
|
+
for (const fontFile of fontFiles) {
|
|
111
|
+
const relativePath = path.relative(publicDir, path.dirname(fontFile))
|
|
112
|
+
const baseName = path.basename(fontFile).replace(/\.(ttf|otf|woff)$/i, '')
|
|
103
113
|
const msdfJsonPath = path.join(msdfOutputDir, relativePath, `${baseName}.msdf.json`)
|
|
104
114
|
const msdfPngPath = path.join(msdfOutputDir, relativePath, `${baseName}.msdf.png`)
|
|
105
115
|
|
|
106
116
|
// Check if MSDF files are generated, if not, generate them
|
|
107
117
|
if (!fs.existsSync(msdfJsonPath) || !fs.existsSync(msdfPngPath)) {
|
|
108
|
-
console.log(`Generating missing MSDF files for ${
|
|
109
|
-
await generateSDF(
|
|
118
|
+
console.log(`Generating missing MSDF files for ${fontFile}`)
|
|
119
|
+
await generateSDF(fontFile, path.join(msdfOutputDir, relativePath))
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
122
|
|
|
@@ -129,17 +139,17 @@ const generateSDF = async (inputFilePath, outputDirPath) => {
|
|
|
129
139
|
else console.error('Failed to generate MSDF file')
|
|
130
140
|
}
|
|
131
141
|
|
|
132
|
-
//
|
|
133
|
-
const
|
|
142
|
+
// Finds all font files (.ttf, .otf, .woff) in a directory
|
|
143
|
+
const findAllFontFiles = (dir, filesList = []) => {
|
|
134
144
|
const files = fs.readdirSync(dir, { withFileTypes: true })
|
|
135
145
|
|
|
136
146
|
files.forEach((file) => {
|
|
137
147
|
if (file.isDirectory()) {
|
|
138
148
|
const dirPath = path.join(dir, file.name)
|
|
139
|
-
|
|
149
|
+
findAllFontFiles(dirPath, filesList)
|
|
140
150
|
} else {
|
|
141
|
-
// Check for
|
|
142
|
-
if (file.name.match(/\.ttf$/i)) {
|
|
151
|
+
// Check for supported font extensions
|
|
152
|
+
if (file.name.match(/\.(ttf|otf|woff)$/i)) {
|
|
143
153
|
filesList.push(path.join(dir, file.name))
|
|
144
154
|
}
|
|
145
155
|
}
|