@linear_non/stellar-kit 3.0.7 → 3.0.9
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/classes/ImageLoader.js +34 -8
- package/core/PageEngine.js +13 -4
- package/events/Emitter.js +4 -1
- package/events/Mouse.js +1 -3
- package/events/VirtualScroll.js +1 -1
- package/kitStore.js +25 -1
- package/package.json +2 -2
- package/utils/math.js +2 -2
- package/utils/sniffer.js +2 -2
- package/utils/support.js +1 -1
package/classes/ImageLoader.js
CHANGED
|
@@ -24,6 +24,8 @@ export default class ImageLoader {
|
|
|
24
24
|
|
|
25
25
|
this._results = new Map() // url -> HTMLImageElement
|
|
26
26
|
this._objectURLs = [] // for revoke
|
|
27
|
+
this._worker = null // shared worker instance
|
|
28
|
+
this._workerURL = null // blob URL for cleanup
|
|
27
29
|
}
|
|
28
30
|
|
|
29
31
|
async load() {
|
|
@@ -61,6 +63,9 @@ export default class ImageLoader {
|
|
|
61
63
|
|
|
62
64
|
await Promise.all(toLoad.map(url => this._loadOne(url)))
|
|
63
65
|
|
|
66
|
+
// Terminate shared worker if created
|
|
67
|
+
this._terminateWorker()
|
|
68
|
+
|
|
64
69
|
// build ordered result (use cache first, then freshly loaded)
|
|
65
70
|
this.images = urls.map(u => this.cache?.get(u) || this._results.get(u) || null)
|
|
66
71
|
this.isLoaded = true
|
|
@@ -69,19 +74,34 @@ export default class ImageLoader {
|
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
_createInlineWorker() {
|
|
77
|
+
if (this._worker) return this._worker
|
|
78
|
+
|
|
72
79
|
const code = `
|
|
73
80
|
self.onmessage = async (e) => {
|
|
74
|
-
const { url } = e.data;
|
|
81
|
+
const { url, id } = e.data;
|
|
75
82
|
try {
|
|
76
83
|
const res = await fetch(url);
|
|
77
84
|
const blob = await res.blob();
|
|
78
|
-
self.postMessage({ url, blob });
|
|
85
|
+
self.postMessage({ url, id, blob });
|
|
79
86
|
} catch (err) {
|
|
80
|
-
self.postMessage({ url, error: String(err) });
|
|
87
|
+
self.postMessage({ url, id, error: String(err) });
|
|
81
88
|
}
|
|
82
89
|
};`
|
|
83
90
|
const blob = new Blob([code], { type: "application/javascript" })
|
|
84
|
-
|
|
91
|
+
this._workerURL = URL.createObjectURL(blob)
|
|
92
|
+
this._worker = new Worker(this._workerURL)
|
|
93
|
+
return this._worker
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
_terminateWorker() {
|
|
97
|
+
if (this._worker) {
|
|
98
|
+
this._worker.terminate()
|
|
99
|
+
this._worker = null
|
|
100
|
+
}
|
|
101
|
+
if (this._workerURL) {
|
|
102
|
+
URL.revokeObjectURL(this._workerURL)
|
|
103
|
+
this._workerURL = null
|
|
104
|
+
}
|
|
85
105
|
}
|
|
86
106
|
|
|
87
107
|
async _loadOne(url) {
|
|
@@ -89,20 +109,25 @@ export default class ImageLoader {
|
|
|
89
109
|
if (this.useWorker && typeof Worker !== "undefined") {
|
|
90
110
|
return new Promise(resolve => {
|
|
91
111
|
const w = this._createInlineWorker()
|
|
92
|
-
|
|
112
|
+
const id = url // use url as unique message id
|
|
113
|
+
|
|
114
|
+
const handler = async e => {
|
|
115
|
+
if (e.data.id !== id) return // not our message
|
|
116
|
+
w.removeEventListener("message", handler)
|
|
117
|
+
|
|
93
118
|
const { blob, error } = e.data
|
|
94
119
|
if (error || !blob) {
|
|
95
120
|
this._bumpProgress()
|
|
96
|
-
w.terminate()
|
|
97
121
|
return resolve(null)
|
|
98
122
|
}
|
|
99
123
|
const img = await this._blobToImage(blob)
|
|
100
124
|
this._store(url, img)
|
|
101
125
|
this._bumpProgress()
|
|
102
|
-
w.terminate()
|
|
103
126
|
resolve(img)
|
|
104
127
|
}
|
|
105
|
-
|
|
128
|
+
|
|
129
|
+
w.addEventListener("message", handler)
|
|
130
|
+
w.postMessage({ url, id })
|
|
106
131
|
})
|
|
107
132
|
}
|
|
108
133
|
|
|
@@ -155,6 +180,7 @@ export default class ImageLoader {
|
|
|
155
180
|
}
|
|
156
181
|
|
|
157
182
|
destroy() {
|
|
183
|
+
this._terminateWorker()
|
|
158
184
|
this._objectURLs.forEach(u => URL.revokeObjectURL(u))
|
|
159
185
|
this._objectURLs.length = 0
|
|
160
186
|
this.images = []
|
package/core/PageEngine.js
CHANGED
|
@@ -123,6 +123,8 @@ export default class PageEngine {
|
|
|
123
123
|
this.smooth = smooth
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
this.trackImages()
|
|
127
|
+
|
|
126
128
|
this.manager = new Manager()
|
|
127
129
|
|
|
128
130
|
if (this.manager && this.components.length) {
|
|
@@ -132,11 +134,18 @@ export default class PageEngine {
|
|
|
132
134
|
}
|
|
133
135
|
|
|
134
136
|
this.manager.initialize()
|
|
135
|
-
this.
|
|
137
|
+
this.resize()
|
|
136
138
|
|
|
137
139
|
this.on()
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Trigger entry animations on all components.
|
|
144
|
+
* Call this from the page/renderer at the appropriate moment
|
|
145
|
+
* (e.g. after loader completes or onEnterCompleted).
|
|
146
|
+
*/
|
|
147
|
+
animateIn() {
|
|
148
|
+
this.manager?.animateIn?.()
|
|
140
149
|
}
|
|
141
150
|
|
|
142
151
|
/**
|
|
@@ -166,7 +175,7 @@ export default class PageEngine {
|
|
|
166
175
|
|
|
167
176
|
// Setup ScrollTrigger scroller proxy
|
|
168
177
|
ScrollTrigger.scrollerProxy(wrapper, {
|
|
169
|
-
scrollTop:
|
|
178
|
+
scrollTop: value => {
|
|
170
179
|
if (value !== undefined) {
|
|
171
180
|
this.lenis.scrollTo(value, { immediate: true })
|
|
172
181
|
}
|
package/events/Emitter.js
CHANGED
|
@@ -33,7 +33,7 @@ class Emitter {
|
|
|
33
33
|
}
|
|
34
34
|
this.on(event, onceCallback, priority)
|
|
35
35
|
return () => {
|
|
36
|
-
this.off(event,
|
|
36
|
+
this.off(event, onceCallback)
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -53,6 +53,9 @@ const EVENTS = {
|
|
|
53
53
|
APP_MOUSEMOVE: "mousemove",
|
|
54
54
|
APP_MOUSEDOWN: "mousedown",
|
|
55
55
|
APP_MOUSEUP: "mouseup",
|
|
56
|
+
APP_ROUTE_IN: "route:in",
|
|
57
|
+
APP_ROUTE_OUT: "route:out",
|
|
58
|
+
APP_ROUTE_END: "route:end",
|
|
56
59
|
APP_SPLITTEXT_READY: "splittext:ready",
|
|
57
60
|
APP_IMAGES_LOADED: "images:loaded",
|
|
58
61
|
APP_IMAGES_PROGRESS: "images:progress",
|
package/events/Mouse.js
CHANGED
|
@@ -15,8 +15,6 @@ export default class Mouse {
|
|
|
15
15
|
down: sniffer.isDevice ? "touchstart" : "mousedown",
|
|
16
16
|
up: sniffer.isDevice ? "touchend" : "mouseup",
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
this.on()
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
on() {
|
|
@@ -54,7 +52,7 @@ export default class Mouse {
|
|
|
54
52
|
onUp = e => {
|
|
55
53
|
const { x, target } = this.getPos(e)
|
|
56
54
|
this.state.off = x
|
|
57
|
-
const isClick = Math.abs(this.state.on - this.state.off)
|
|
55
|
+
const isClick = Math.abs(this.state.on - this.state.off) <= 10
|
|
58
56
|
emitter.emit(EVENTS.APP_MOUSEUP, { x, target, isClick })
|
|
59
57
|
}
|
|
60
58
|
}
|
package/events/VirtualScroll.js
CHANGED
package/kitStore.js
CHANGED
|
@@ -40,12 +40,36 @@ export const kitStore = {
|
|
|
40
40
|
breakpoints,
|
|
41
41
|
mouse,
|
|
42
42
|
flags,
|
|
43
|
-
pageContent: null,
|
|
44
43
|
assets,
|
|
44
|
+
|
|
45
|
+
/** @type {HTMLElement | null} — main content container (#app) */
|
|
46
|
+
pageContent: null,
|
|
47
|
+
|
|
48
|
+
/** @type {HTMLElement | null} — current page/view element ([data-taxi-view]) */
|
|
49
|
+
currentPage: null,
|
|
50
|
+
|
|
51
|
+
/** @type {URL | string | null} — current URL (set by Application) */
|
|
52
|
+
currentURL: null,
|
|
53
|
+
|
|
54
|
+
/** @type {HTMLElement | null} — loader element (set by Application) */
|
|
55
|
+
load: null,
|
|
56
|
+
|
|
45
57
|
/**
|
|
46
58
|
* Scroll scroller element (wrapper for Lenis, pageContent for internal scroll).
|
|
47
59
|
* Used by ScrollTrigger components to get the correct scroller.
|
|
48
60
|
* @type {HTMLElement | null}
|
|
49
61
|
*/
|
|
50
62
|
scroller: null,
|
|
63
|
+
|
|
64
|
+
/** @type {import("./events/Raf").default | null} */
|
|
65
|
+
raf: null,
|
|
66
|
+
|
|
67
|
+
/** @type {import("./events/Scroll").default | null} */
|
|
68
|
+
scroll: null,
|
|
69
|
+
|
|
70
|
+
/** @type {import("./events/Resize").default | null} */
|
|
71
|
+
resize: null,
|
|
72
|
+
|
|
73
|
+
/** @type {any | null} — Taxi router instance (if attached via Application.attachTaxi()) */
|
|
74
|
+
taxi: null,
|
|
51
75
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linear_non/stellar-kit",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.9",
|
|
4
4
|
"description": "Stellar frontend core for Non-Linear Studio projects.",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "
|
|
6
|
+
"main": "./core/index.js",
|
|
7
7
|
"sass": "./styles/index.scss",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./kitStore.js",
|
package/utils/math.js
CHANGED
|
@@ -31,7 +31,7 @@ export const clamp = (val, min, max) => Math.min(Math.max(val, min), max)
|
|
|
31
31
|
* @param {number} [p=3] - Decimal precision
|
|
32
32
|
* @returns {number}
|
|
33
33
|
*/
|
|
34
|
-
export const round = (n, p) => {
|
|
35
|
-
const precision =
|
|
34
|
+
export const round = (n, p = 3) => {
|
|
35
|
+
const precision = Math.pow(10, p)
|
|
36
36
|
return Math.round(n * precision) / precision
|
|
37
37
|
}
|
package/utils/sniffer.js
CHANGED
|
@@ -75,7 +75,7 @@ export const sniffer = {
|
|
|
75
75
|
},
|
|
76
76
|
|
|
77
77
|
get isWindows() {
|
|
78
|
-
return
|
|
78
|
+
return /windows/i.test(this.uA)
|
|
79
79
|
},
|
|
80
80
|
|
|
81
81
|
get isChrome() {
|
|
@@ -89,7 +89,7 @@ export const sniffer = {
|
|
|
89
89
|
},
|
|
90
90
|
|
|
91
91
|
get isMac() {
|
|
92
|
-
return
|
|
92
|
+
return /macintosh|mac os x/i.test(this.uA)
|
|
93
93
|
},
|
|
94
94
|
|
|
95
95
|
get isDesktop() {
|
package/utils/support.js
CHANGED
|
@@ -14,7 +14,7 @@ export const supportMouseTouch = () => {
|
|
|
14
14
|
hasTouch:
|
|
15
15
|
"ontouchstart" in window ||
|
|
16
16
|
window.TouchEvent ||
|
|
17
|
-
(
|
|
17
|
+
(navigator.maxTouchPoints && navigator.maxTouchPoints > 0),
|
|
18
18
|
hasTouchWin: navigator.msMaxTouchPoints && navigator.msMaxTouchPoints > 1,
|
|
19
19
|
hasPointer: !!window.navigator.msPointerEnabled,
|
|
20
20
|
hasKeyDown: "onkeydown" in document,
|