@linear_non/stellar-libs 1.0.42 → 1.0.44
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/package.json +2 -2
- package/src/Smooth/index.js +26 -30
- package/src/SplitOnScroll/index.js +57 -74
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linear_non/stellar-libs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.44",
|
|
4
4
|
"description": "Reusable JavaScript libraries for Non-Linear Studio projects.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"author": "Non-Linear Studio",
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@linear_non/stellar-kit": "^2.1.
|
|
28
|
+
"@linear_non/stellar-kit": "^2.1.17"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@linear_non/prettier-config": "^1.0.6",
|
package/src/Smooth/index.js
CHANGED
|
@@ -12,16 +12,9 @@ export default class Smooth {
|
|
|
12
12
|
this.sections = null
|
|
13
13
|
this.scrollbar = null
|
|
14
14
|
this.dpr = Math.max(1, Math.round(window.devicePixelRatio || 1))
|
|
15
|
-
|
|
16
15
|
this.init()
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
/**
|
|
20
|
-
* - top / bottom: virtual layout positions
|
|
21
|
-
* - offset: parallax centering adjustment
|
|
22
|
-
* - speed: dataset speed multiplier
|
|
23
|
-
* - parent: optional reference to another section for nested offsets
|
|
24
|
-
*/
|
|
25
18
|
getSections() {
|
|
26
19
|
const { isSmooth } = kitStore.flags
|
|
27
20
|
if (!this.elems || !isSmooth) return
|
|
@@ -31,21 +24,17 @@ export default class Smooth {
|
|
|
31
24
|
|
|
32
25
|
this.elems.forEach(el => {
|
|
33
26
|
el.style.transform = "translate3d(0, 0, 0)"
|
|
34
|
-
|
|
35
|
-
const speed =
|
|
27
|
+
const raw = el.dataset.speed != null ? parseFloat(el.dataset.speed) : 1
|
|
28
|
+
const speed = Number.isFinite(raw) ? raw : 1
|
|
36
29
|
const { height, offset } = this.getVars(el, speed)
|
|
37
30
|
|
|
38
31
|
const top = cursor
|
|
39
32
|
const bottom = top + height
|
|
40
|
-
cursor = bottom
|
|
41
33
|
|
|
42
|
-
|
|
34
|
+
cursor = bottom
|
|
43
35
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (obj.el === parent) parent = obj
|
|
47
|
-
})
|
|
48
|
-
}
|
|
36
|
+
const parentEl = el.parentElement?.closest?.("[data-smooth]")
|
|
37
|
+
const parent = parentEl ? this.sections.find(s => s.el === parentEl) || null : null
|
|
49
38
|
|
|
50
39
|
this.sections.push({
|
|
51
40
|
el,
|
|
@@ -56,11 +45,14 @@ export default class Smooth {
|
|
|
56
45
|
speed,
|
|
57
46
|
out: true,
|
|
58
47
|
transform: 0,
|
|
48
|
+
_roundedY: 0,
|
|
59
49
|
})
|
|
60
50
|
})
|
|
61
51
|
}
|
|
62
52
|
|
|
63
53
|
tick = ({ current }) => {
|
|
54
|
+
const { isSmooth, isResizing } = kitStore.flags
|
|
55
|
+
if (!isSmooth || isResizing) return
|
|
64
56
|
this.current = current
|
|
65
57
|
this.transformSections()
|
|
66
58
|
}
|
|
@@ -71,11 +63,14 @@ export default class Smooth {
|
|
|
71
63
|
|
|
72
64
|
this.sections.forEach(section => {
|
|
73
65
|
const { isVisible, transform } = this.isVisible(section)
|
|
74
|
-
|
|
75
66
|
if (isVisible || isResizing || !section.out) {
|
|
67
|
+
const { y, css } = this.getTransform(transform)
|
|
68
|
+
if (y !== section._roundedY) {
|
|
69
|
+
section.el.style.transform = css
|
|
70
|
+
section._roundedY = y
|
|
71
|
+
}
|
|
76
72
|
section.out = !isVisible
|
|
77
73
|
section.transform = transform
|
|
78
|
-
section.el.style.transform = this.getTransform(transform)
|
|
79
74
|
}
|
|
80
75
|
})
|
|
81
76
|
}
|
|
@@ -83,15 +78,11 @@ export default class Smooth {
|
|
|
83
78
|
isVisible(section) {
|
|
84
79
|
const { vh } = kitStore.sizes
|
|
85
80
|
const { top, bottom, offset, speed, parent } = section
|
|
86
|
-
|
|
87
81
|
const extra = (parent && parent.transform) || 0
|
|
88
|
-
|
|
89
82
|
const translate = this.current * speed
|
|
90
83
|
const transform = translate - offset - extra
|
|
91
|
-
|
|
92
84
|
const start = top - translate
|
|
93
85
|
const end = bottom - translate
|
|
94
|
-
|
|
95
86
|
const isVisible = end > 0 && start < vh
|
|
96
87
|
|
|
97
88
|
return { isVisible, transform }
|
|
@@ -100,8 +91,7 @@ export default class Smooth {
|
|
|
100
91
|
getTransform(transform) {
|
|
101
92
|
let y = -transform
|
|
102
93
|
y = Math.round(y * this.dpr) / this.dpr
|
|
103
|
-
|
|
104
|
-
return `translate3d(0, ${y}px, 0)`
|
|
94
|
+
return { y, css: `translate3d(0, ${y}px, 0)` }
|
|
105
95
|
}
|
|
106
96
|
|
|
107
97
|
getVars(el, speed) {
|
|
@@ -119,26 +109,32 @@ export default class Smooth {
|
|
|
119
109
|
|
|
120
110
|
resize = () => {
|
|
121
111
|
const { isSmooth } = kitStore.flags
|
|
112
|
+
|
|
122
113
|
if (!isSmooth) return
|
|
123
114
|
|
|
124
|
-
this.
|
|
115
|
+
this.scroll?.setScrollBounds()
|
|
116
|
+
|
|
117
|
+
const { fh } = kitStore.sizes
|
|
118
|
+
this.current = Math.min(Math.max(this.current, 0), fh || 0)
|
|
119
|
+
|
|
120
|
+
this.getSections()
|
|
125
121
|
emitter.emit(EVENTS.APP_SMOOTH_RESIZE)
|
|
122
|
+
this.transformSections()
|
|
123
|
+
this.scrollbar?.update()
|
|
126
124
|
}
|
|
127
125
|
|
|
128
126
|
update(elems) {
|
|
129
127
|
kitStore.flags.isResizing = true
|
|
130
|
-
|
|
131
128
|
this.scroll.setScrollBounds()
|
|
132
129
|
this.elems = elems || qsa("[data-smooth]")
|
|
133
130
|
this.scrollbar?.update()
|
|
134
|
-
|
|
135
131
|
this.getSections()
|
|
136
132
|
this.transformSections()
|
|
137
|
-
|
|
138
133
|
kitStore.flags.isResizing = false
|
|
139
134
|
}
|
|
140
135
|
|
|
141
136
|
clean() {
|
|
137
|
+
if (this.sections) this.sections.forEach(s => (s.el.style.transform = ""))
|
|
142
138
|
this.elems = this.sections = null
|
|
143
139
|
}
|
|
144
140
|
|
|
@@ -154,15 +150,15 @@ export default class Smooth {
|
|
|
154
150
|
|
|
155
151
|
destroy() {
|
|
156
152
|
this.off()
|
|
153
|
+
this.scrollbar?.destroy()
|
|
157
154
|
this.clean()
|
|
158
155
|
}
|
|
159
156
|
|
|
160
157
|
init(elems) {
|
|
161
158
|
this.elems = elems || qsa("[data-smooth]")
|
|
162
159
|
|
|
163
|
-
const container = kitStore.currentPage
|
|
164
160
|
this.scrollbar = new Scrollbar({
|
|
165
|
-
container,
|
|
161
|
+
container: kitStore.currentPage,
|
|
166
162
|
})
|
|
167
163
|
|
|
168
164
|
this.on()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EVENTS
|
|
1
|
+
import { EVENTS } from "@linear_non/stellar-kit/events"
|
|
2
2
|
import { Observer, reverseSplit, splitText } from "@linear_non/stellar-kit/plugins"
|
|
3
3
|
|
|
4
4
|
const NOOP = () => {}
|
|
@@ -13,64 +13,62 @@ function normalizeTargets(splitTargets) {
|
|
|
13
13
|
export default class SplitonScroll {
|
|
14
14
|
constructor({
|
|
15
15
|
el,
|
|
16
|
-
splitText
|
|
16
|
+
splitText,
|
|
17
17
|
isReady,
|
|
18
18
|
reverse,
|
|
19
|
+
resize,
|
|
19
20
|
start = "top bottom",
|
|
20
21
|
end = "bottom top",
|
|
21
22
|
scrub = false,
|
|
22
23
|
once = true,
|
|
23
24
|
}) {
|
|
24
25
|
this.element = el
|
|
25
|
-
this.targets = normalizeTargets(
|
|
26
|
+
this.targets = normalizeTargets(splitText)
|
|
26
27
|
|
|
27
28
|
this.splits = null
|
|
28
29
|
this.groups = null
|
|
29
30
|
|
|
30
31
|
this.isReadyCallback = isReady || NOOP
|
|
31
32
|
this.reverseCallback = reverse || NOOP
|
|
33
|
+
this.isResizeCallback = resize || NOOP
|
|
32
34
|
this.start = start
|
|
33
35
|
this.end = end
|
|
34
36
|
this.scrub = scrub
|
|
35
37
|
this.once = once
|
|
36
38
|
|
|
37
|
-
this._readyNotified = false
|
|
38
|
-
this._resolveReady = null
|
|
39
39
|
this.ready = new Promise(resolve => {
|
|
40
40
|
this._resolveReady = resolve
|
|
41
41
|
})
|
|
42
42
|
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
this._onResizeStart = this._onResizeStart.bind(this)
|
|
46
|
-
this._onSmoothResize = this._onSmoothResize.bind(this)
|
|
47
|
-
this._offResizeStart = null
|
|
48
|
-
this._offSmoothResize = null
|
|
43
|
+
this._readyFired = false
|
|
44
|
+
this._rebuilding = false
|
|
49
45
|
|
|
50
46
|
if (!this.element || !this.targets.length) {
|
|
51
|
-
|
|
52
|
-
this._notifyReadyOnce(payload)
|
|
47
|
+
this._notifyReadyOnce([])
|
|
53
48
|
return
|
|
54
49
|
}
|
|
55
50
|
|
|
51
|
+
this.init()
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
init() {
|
|
55
|
+
// Initialize observer
|
|
56
56
|
this.addObserver()
|
|
57
|
-
this.addResizeListeners()
|
|
58
57
|
|
|
58
|
+
// If already in view, handle immediately
|
|
59
59
|
if (this.observer && (this.observer.isActive || this.observer.progress > 0)) {
|
|
60
60
|
this.handleEnter()
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
this.
|
|
67
|
-
|
|
68
|
-
this.isReadyCallback(payload.splits, payload.groups)
|
|
64
|
+
// Set is ready only once
|
|
65
|
+
_notifyReadyOnce(splits, groups) {
|
|
66
|
+
if (this._readyFired) return
|
|
67
|
+
this._readyFired = true
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
69
|
+
this.isReadyCallback(splits, groups)
|
|
70
|
+
this._resolveReady?.({ splits, groups })
|
|
71
|
+
this._resolveReady = null
|
|
74
72
|
}
|
|
75
73
|
|
|
76
74
|
addObserver() {
|
|
@@ -86,78 +84,66 @@ export default class SplitonScroll {
|
|
|
86
84
|
this.observer.on("leave", () => this.handleLeave())
|
|
87
85
|
}
|
|
88
86
|
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
|
|
87
|
+
async resize() {
|
|
88
|
+
// if not built yet, just build once
|
|
89
|
+
if (!this.splits) return
|
|
92
90
|
|
|
93
|
-
//
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
// revert then rebuild
|
|
92
|
+
reverseSplit(this.splits)
|
|
93
|
+
this.splits = null
|
|
94
|
+
this.groups = null
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this._offResizeStart()
|
|
100
|
-
this._offResizeStart = null
|
|
101
|
-
}
|
|
102
|
-
if (this._offSmoothResize) {
|
|
103
|
-
this._offSmoothResize()
|
|
104
|
-
this._offSmoothResize = null
|
|
105
|
-
}
|
|
96
|
+
// rebuild splits
|
|
97
|
+
await this.refreshSplits()
|
|
106
98
|
}
|
|
107
99
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (this.splits) {
|
|
112
|
-
reverseSplit(this.splits)
|
|
113
|
-
|
|
114
|
-
this.splits = null
|
|
115
|
-
this.groups = null
|
|
116
|
-
}
|
|
100
|
+
async handleEnter() {
|
|
101
|
+
const splitEmitter = splitText(this.targets)
|
|
117
102
|
|
|
118
|
-
|
|
119
|
-
|
|
103
|
+
const { splits, groups } = await new Promise(resolve => {
|
|
104
|
+
const onReady = (readySplits, groupMap) => {
|
|
105
|
+
// Clean up listener
|
|
106
|
+
if (splitEmitter.off) {
|
|
107
|
+
splitEmitter.off(EVENTS.APP_SPLITTEXT_READY, onReady)
|
|
108
|
+
}
|
|
120
109
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
110
|
+
resolve({
|
|
111
|
+
splits: readySplits || [],
|
|
112
|
+
groups: groupMap || {},
|
|
113
|
+
})
|
|
114
|
+
}
|
|
124
115
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
116
|
+
// Listen for ready event once
|
|
117
|
+
splitEmitter.once(EVENTS.APP_SPLITTEXT_READY, onReady)
|
|
118
|
+
})
|
|
128
119
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
120
|
+
this.splits = splits
|
|
121
|
+
this.groups = groups
|
|
132
122
|
|
|
133
|
-
this.
|
|
123
|
+
this._notifyReadyOnce(splits, groups)
|
|
134
124
|
}
|
|
135
125
|
|
|
136
|
-
async
|
|
137
|
-
|
|
126
|
+
async refreshSplits() {
|
|
127
|
+
if (this._rebuilding) return
|
|
128
|
+
this._rebuilding = true
|
|
138
129
|
|
|
130
|
+
// (Re)build fresh splits
|
|
131
|
+
const emitter = splitText(this.targets)
|
|
139
132
|
const { splits, groups } = await new Promise(resolve => {
|
|
140
133
|
const onReady = (readySplits, groupMap) => {
|
|
141
|
-
if (typeof splitEmitter.off === "function") {
|
|
142
|
-
splitEmitter.off(EVENTS.APP_SPLITTEXT_READY, onReady)
|
|
143
|
-
}
|
|
144
134
|
resolve({
|
|
145
135
|
splits: readySplits || [],
|
|
146
136
|
groups: groupMap || {},
|
|
147
137
|
})
|
|
148
138
|
}
|
|
149
|
-
|
|
150
|
-
if (typeof splitEmitter.once === "function") {
|
|
151
|
-
splitEmitter.once(EVENTS.APP_SPLITTEXT_READY, onReady)
|
|
152
|
-
} else {
|
|
153
|
-
splitEmitter.on(EVENTS.APP_SPLITTEXT_READY, onReady)
|
|
154
|
-
}
|
|
139
|
+
emitter.once(EVENTS.APP_SPLITTEXT_READY, onReady)
|
|
155
140
|
})
|
|
156
141
|
|
|
157
142
|
this.splits = splits
|
|
158
143
|
this.groups = groups
|
|
144
|
+
this._rebuilding = false
|
|
159
145
|
|
|
160
|
-
this.
|
|
146
|
+
this.isResizeCallback(splits, groups)
|
|
161
147
|
}
|
|
162
148
|
|
|
163
149
|
handleLeave() {
|
|
@@ -179,9 +165,6 @@ export default class SplitonScroll {
|
|
|
179
165
|
}
|
|
180
166
|
|
|
181
167
|
destroy() {
|
|
182
|
-
this.observer?.kill()
|
|
183
|
-
this.removeResizeListeners()
|
|
184
|
-
|
|
185
168
|
if (this.splits) {
|
|
186
169
|
reverseSplit(this.splits)
|
|
187
170
|
}
|