@linear_non/stellar-kit 1.0.5 → 1.0.7

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/events/Raf.js CHANGED
@@ -41,8 +41,10 @@ export default class Raf {
41
41
  }
42
42
 
43
43
  getScroll() {
44
- const { pageContent } = kitStore
45
- return sniffer.isDevice ? pageContent.parentNode.scrollTop : this.scroll.rounded
44
+ const { pageContent, flags } = kitStore
45
+ const container = pageContent ? pageContent.parentNode : document.body
46
+
47
+ return flags.isSmooth ? this.scroll.rounded : container.scrollTop
46
48
  }
47
49
 
48
50
  clamp() {
@@ -1,11 +1,9 @@
1
1
  import gsap from "gsap"
2
2
  import { ScrollTrigger } from "gsap/ScrollTrigger"
3
- import SplitText from "./SplitText"
4
- import CustomEase from "./CustomEase"
3
+ import { SplitText } from "gsap/SplitText"
4
+ import { CustomEase } from "gsap/CustomEase"
5
5
 
6
- gsap.registerPlugin(ScrollTrigger)
7
- gsap.registerPlugin(SplitText)
8
- gsap.registerPlugin(CustomEase)
6
+ gsap.registerPlugin(ScrollTrigger, SplitText, CustomEase)
9
7
 
10
8
  const customEase = CustomEase.create(
11
9
  "custom",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linear_non/stellar-kit",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Stellar frontend core for Non-Linear Studio projects.",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -36,7 +36,7 @@
36
36
  "author": "Non-Linear Studio",
37
37
  "license": "MIT",
38
38
  "dependencies": {
39
- "gsap": "^3.12.5",
39
+ "gsap": "^3.13.0",
40
40
  "lethargy": "^1.0.9",
41
41
  "lodash.debounce": "^4.0.8"
42
42
  },
@@ -1,124 +0,0 @@
1
- import kitStore from "../kitStore"
2
- import { emitter, EVENTS, Raf } from "../events"
3
-
4
- export default class Scrollbar {
5
- constructor(obj) {
6
- this.container = obj.container || document.body
7
- this.el = null
8
- this.handle = null
9
- this.touching = false
10
-
11
- this.state = {
12
- clicked: false,
13
- scale: 0,
14
- current: 0,
15
- }
16
- this.height = 0
17
- this.init()
18
- }
19
-
20
- init() {
21
- this.create()
22
- this.setBounds()
23
- this.on()
24
- }
25
-
26
- on() {
27
- emitter.on(EVENTS.APP_TICK, this.tick)
28
- emitter.on(EVENTS.APP_RESIZE, this.resize)
29
- this.handle.addEventListener("mousedown", this.mouseDown)
30
- window.addEventListener("mouseup", this.mouseUp)
31
- window.addEventListener("mousemove", this.mouseMove)
32
- }
33
-
34
- off() {
35
- emitter.off(EVENTS.APP_TICK, this.tick)
36
- emitter.off(EVENTS.APP_RESIZE, this.resize)
37
- this.handle.removeEventListener("mousedown", this.mouseDown)
38
- window.removeEventListener("mouseup", this.mouseUp)
39
- window.removeEventListener("mousemove", this.mouseMove)
40
- }
41
-
42
- mouseDown = () => {
43
- this.touching = true
44
- document.body.style.userSelect = "none"
45
- document.body.style.webkitUserSelect = "none"
46
- document.body.style.pointerEvents = "none"
47
- }
48
-
49
- mouseUp = () => {
50
- this.touching = false
51
- document.body.style.userSelect = "inherit"
52
- document.body.style.webkitUserSelect = "inherit"
53
- document.body.style.pointerEvents = "inherit"
54
- }
55
-
56
- mouseMove = e => {
57
- if (this.touching === true) {
58
- const { isLocked } = kitStore.flags
59
-
60
- if (isLocked) return
61
-
62
- kitStore.raf.scroll.target = e.clientY * this.state.scale
63
- kitStore.raf.clamp()
64
- }
65
- }
66
-
67
- setBounds() {
68
- const { vh, fh } = kitStore.sizes
69
- const scrollLimit = fh
70
- this.state.scale = (scrollLimit + vh) / vh
71
- this.handle.style.height = `${vh / this.state.scale}px`
72
- }
73
-
74
- tick = ({ current }) => {
75
- const scroll = current / this.state.scale
76
- this.state.current = scroll
77
- this.handle.style.transform = `translate3d(0, ${this.state.current}px, 0)`
78
- }
79
-
80
- resize = () => {
81
- this.setBounds()
82
- }
83
-
84
- calcScroll(e) {
85
- const delta = e.clientY * this.state.scale
86
- Raf.target = delta
87
- Raf.clampTarget()
88
- }
89
-
90
- create() {
91
- this.el = document.createElement("div")
92
- this.handle = document.createElement("div")
93
- this.el.classList.add("scrollbar")
94
- this.handle.classList.add("handle")
95
-
96
- Object.assign(this.el.style, {
97
- position: "fixed",
98
- top: 0,
99
- right: 0,
100
- height: "100%",
101
- pointerEvents: "all",
102
- })
103
-
104
- Object.assign(this.handle.style, {
105
- position: "absolute",
106
- top: 0,
107
- left: 0,
108
- width: "100%",
109
- cursor: "pointer",
110
- zIndex: 101,
111
- })
112
-
113
- this.container.appendChild(this.el)
114
- this.el.appendChild(this.handle)
115
- }
116
-
117
- update() {
118
- this.setBounds()
119
- }
120
-
121
- destroy() {
122
- this.off()
123
- }
124
- }
package/classes/Smooth.js DELETED
@@ -1,146 +0,0 @@
1
- // Smooth.js
2
- import kitStore from "../kitStore"
3
- import Scrollbar from "./Scrollbar"
4
- import { emitter, EVENTS } from "../events"
5
- import { qs, qsa, bounds } from "../utils"
6
-
7
- export default class Smooth {
8
- constructor(obj) {
9
- this.scroll = obj.scroll
10
- this.el = qs("[data-view]")
11
- this.elems = null
12
- this.current = 0
13
- this.threshold = 100
14
- this.sections = null
15
- this.scrollbar = null
16
- this.init()
17
- }
18
-
19
- getSections() {
20
- const { isSmooth } = kitStore.flags
21
- if (!this.elems || !isSmooth) return
22
-
23
- this.sections = []
24
- this.elems.forEach(el => {
25
- el.style.transform = "translate3d(0, 0, 0)"
26
- const speed = el.dataset.speed || 1
27
- const { top, bottom, offset } = this.getVars(el, speed)
28
- let parent = el.parentNode.closest("[data-smooth]")
29
-
30
- if (parent) {
31
- this.sections.some(obj => {
32
- if (obj.el === parent) parent = obj
33
- })
34
- }
35
-
36
- this.sections.push({
37
- el,
38
- parent,
39
- top,
40
- bottom,
41
- offset,
42
- speed,
43
- out: true,
44
- transform: 0,
45
- })
46
- })
47
- }
48
-
49
- tick = ({ current }) => {
50
- this.current = current
51
- this.transformSections()
52
- }
53
-
54
- transformSections() {
55
- const { isSmooth, isResizing } = kitStore.flags
56
- if (!this.sections || !isSmooth) return
57
-
58
- this.sections.forEach(section => {
59
- const { isVisible, transform } = this.isVisible(section)
60
-
61
- if (isVisible || isResizing || !section.out) {
62
- section.out = !isVisible
63
- section.transform = transform
64
- section.el.style.transform = this.getTransform(transform)
65
- }
66
- })
67
- }
68
-
69
- isVisible(section) {
70
- const { vh } = kitStore.sizes
71
- const { top, bottom, offset, speed, parent } = section
72
-
73
- const extra = (parent && parent.transform) || 0
74
- const translate = this.current * speed
75
- const transform = translate - offset - extra
76
- const start = top - translate
77
- const end = bottom - translate
78
- const isVisible = start < this.threshold + vh && end > -this.threshold
79
-
80
- return { isVisible, transform }
81
- }
82
-
83
- getTransform(transform) {
84
- return `translate3d(0, ${-transform}px, 0)`
85
- }
86
-
87
- getVars(el, speed) {
88
- const { vh } = kitStore.sizes
89
- const rect = bounds(el)
90
- const centering = vh / 2 - rect.height / 2
91
- const offset = rect.top < vh ? 0 : (rect.top - centering) * speed - (rect.top - centering)
92
-
93
- return {
94
- top: rect.top + offset,
95
- bottom: rect.bottom + offset,
96
- offset,
97
- }
98
- }
99
-
100
- resize = () => {
101
- if (!this.sections) return
102
-
103
- this.sections.forEach(section => {
104
- section.el.style.transform = "translate3d(0, 0, 0)"
105
- const { top, bottom, offset } = this.getVars(section.el, section.speed)
106
- Object.assign(section, { top, bottom, offset })
107
- })
108
-
109
- emitter.emit(EVENTS.APP_SMOOTH_RESIZE)
110
- this.transformSections()
111
- }
112
-
113
- update(elems) {
114
- kitStore.flags.isResizing = true
115
-
116
- this.scroll.setScrollBounds()
117
- this.elems = elems || qsa("[data-smooth]")
118
- this.scrollbar.update()
119
- this.getSections()
120
- this.transformSections()
121
-
122
- kitStore.flags.isResizing = false
123
- }
124
-
125
- clean() {
126
- this.elems = this.sections = null
127
- }
128
-
129
- on() {
130
- emitter.on(EVENTS.APP_TICK, this.tick)
131
- emitter.on(EVENTS.APP_RESIZE, this.resize)
132
- }
133
-
134
- off() {
135
- emitter.off(EVENTS.APP_TICK, this.tick)
136
- emitter.off(EVENTS.APP_RESIZE, this.resize)
137
- }
138
-
139
- init(elems) {
140
- this.elems = elems || qsa("[data-smooth]")
141
- this.getSections()
142
- this.scrollbar = new Scrollbar(this.current)
143
- this.on()
144
- this.update()
145
- }
146
- }
@@ -1,275 +0,0 @@
1
- /*!
2
- * CustomEase 3.12.5
3
- * https://gsap.com
4
- *
5
- * @license Copyright 2008-2024, GreenSock. All rights reserved.
6
- * Subject to the terms at https://gsap.com/standard-license or for
7
- * Club GSAP members, the agreement issued with that membership.
8
- * @author: Jack Doyle, jack@greensock.com
9
- */
10
- /* eslint-disable */
11
-
12
- import { stringToRawPath, rawPathToString, transformRawPath } from "./utils/paths.js";
13
-
14
- let gsap, _coreInitted,
15
- _getGSAP = () => gsap || (typeof(window) !== "undefined" && (gsap = window.gsap) && gsap.registerPlugin && gsap),
16
- _initCore = () => {
17
- gsap = _getGSAP();
18
- if (gsap) {
19
- gsap.registerEase("_CE", CustomEase.create);
20
- _coreInitted = 1;
21
- } else {
22
- console.warn("Please gsap.registerPlugin(CustomEase)");
23
- }
24
- },
25
- _bigNum = 1e20,
26
- _round = value => ~~(value * 1000 + (value < 0 ? -.5 : .5)) / 1000,
27
- _bonusValidated = 1, //<name>CustomEase</name>
28
- _numExp = /[-+=.]*\d+[.e\-+]*\d*[e\-+]*\d*/gi, //finds any numbers, including ones that start with += or -=, negative numbers, and ones in scientific notation like 1e-8.
29
- _needsParsingExp = /[cLlsSaAhHvVtTqQ]/g,
30
- _findMinimum = values => {
31
- let l = values.length,
32
- min = _bigNum,
33
- i;
34
- for (i = 1; i < l; i += 6) {
35
- +values[i] < min && (min = +values[i]);
36
- }
37
- return min;
38
- },
39
- //takes all the points and translates/scales them so that the x starts at 0 and ends at 1.
40
- _normalize = (values, height, originY) => {
41
- if (!originY && originY !== 0) {
42
- originY = Math.max(+values[values.length-1], +values[1]);
43
- }
44
- let tx = +values[0] * -1,
45
- ty = -originY,
46
- l = values.length,
47
- sx = 1 / (+values[l - 2] + tx),
48
- sy = -height || ((Math.abs(+values[l - 1] - +values[1]) < 0.01 * (+values[l - 2] - +values[0])) ? _findMinimum(values) + ty : +values[l - 1] + ty),
49
- i;
50
- if (sy) { //typically y ends at 1 (so that the end values are reached)
51
- sy = 1 / sy;
52
- } else { //in case the ease returns to its beginning value, scale everything proportionally
53
- sy = -sx;
54
- }
55
- for (i = 0; i < l; i += 2) {
56
- values[i] = (+values[i] + tx) * sx;
57
- values[i + 1] = (+values[i + 1] + ty) * sy;
58
- }
59
- },
60
- //note that this function returns point objects like {x, y} rather than working with segments which are arrays with alternating x, y values as in the similar function in paths.js
61
- _bezierToPoints = function (x1, y1, x2, y2, x3, y3, x4, y4, threshold, points, index) {
62
- let x12 = (x1 + x2) / 2,
63
- y12 = (y1 + y2) / 2,
64
- x23 = (x2 + x3) / 2,
65
- y23 = (y2 + y3) / 2,
66
- x34 = (x3 + x4) / 2,
67
- y34 = (y3 + y4) / 2,
68
- x123 = (x12 + x23) / 2,
69
- y123 = (y12 + y23) / 2,
70
- x234 = (x23 + x34) / 2,
71
- y234 = (y23 + y34) / 2,
72
- x1234 = (x123 + x234) / 2,
73
- y1234 = (y123 + y234) / 2,
74
- dx = x4 - x1,
75
- dy = y4 - y1,
76
- d2 = Math.abs((x2 - x4) * dy - (y2 - y4) * dx),
77
- d3 = Math.abs((x3 - x4) * dy - (y3 - y4) * dx),
78
- length;
79
- if (!points) {
80
- points = [{x: x1, y: y1}, {x: x4, y: y4}];
81
- index = 1;
82
- }
83
- points.splice(index || points.length - 1, 0, {x: x1234, y: y1234});
84
- if ((d2 + d3) * (d2 + d3) > threshold * (dx * dx + dy * dy)) {
85
- length = points.length;
86
- _bezierToPoints(x1, y1, x12, y12, x123, y123, x1234, y1234, threshold, points, index);
87
- _bezierToPoints(x1234, y1234, x234, y234, x34, y34, x4, y4, threshold, points, index + 1 + (points.length - length));
88
- }
89
- return points;
90
- };
91
-
92
- export class CustomEase {
93
-
94
- constructor(id, data, config) {
95
- _coreInitted || _initCore();
96
- this.id = id;
97
- _bonusValidated && this.setData(data, config);
98
- }
99
-
100
- setData(data, config) {
101
- config = config || {};
102
- data = data || "0,0,1,1";
103
- let values = data.match(_numExp),
104
- closest = 1,
105
- points = [],
106
- lookup = [],
107
- precision = config.precision || 1,
108
- fast = (precision <= 1),
109
- l, a1, a2, i, inc, j, point, prevPoint, p;
110
- this.data = data;
111
- if (_needsParsingExp.test(data) || (~data.indexOf("M") && data.indexOf("C") < 0)) {
112
- values = stringToRawPath(data)[0];
113
- }
114
- l = values.length;
115
- if (l === 4) {
116
- values.unshift(0, 0);
117
- values.push(1, 1);
118
- l = 8;
119
- } else if ((l - 2) % 6) {
120
- throw "Invalid CustomEase";
121
- }
122
- if (+values[0] !== 0 || +values[l - 2] !== 1) {
123
- _normalize(values, config.height, config.originY);
124
- }
125
- this.segment = values;
126
- for (i = 2; i < l; i += 6) {
127
- a1 = {x: +values[i - 2], y: +values[i - 1]};
128
- a2 = {x: +values[i + 4], y: +values[i + 5]};
129
- points.push(a1, a2);
130
- _bezierToPoints(a1.x, a1.y, +values[i], +values[i + 1], +values[i + 2], +values[i + 3], a2.x, a2.y, 1 / (precision * 200000), points, points.length - 1);
131
- }
132
- l = points.length;
133
- for (i = 0; i < l; i++) {
134
- point = points[i];
135
- prevPoint = points[i - 1] || point;
136
- if ((point.x > prevPoint.x || (prevPoint.y !== point.y && prevPoint.x === point.x) || point === prevPoint) && point.x <= 1) { //if a point goes BACKWARD in time or is a duplicate, just drop it. Also it shouldn't go past 1 on the x axis, as could happen in a string like "M0,0 C0,0 0.12,0.68 0.18,0.788 0.195,0.845 0.308,1 0.32,1 0.403,1.005 0.398,1 0.5,1 0.602,1 0.816,1.005 0.9,1 0.91,1 0.948,0.69 0.962,0.615 1.003,0.376 1,0 1,0".
137
- prevPoint.cx = point.x - prevPoint.x; //change in x between this point and the next point (performance optimization)
138
- prevPoint.cy = point.y - prevPoint.y;
139
- prevPoint.n = point;
140
- prevPoint.nx = point.x; //next point's x value (performance optimization, making lookups faster in getRatio()). Remember, the lookup will always land on a spot where it's either this point or the very next one (never beyond that)
141
- if (fast && i > 1 && Math.abs(prevPoint.cy / prevPoint.cx - points[i - 2].cy / points[i - 2].cx) > 2) { //if there's a sudden change in direction, prioritize accuracy over speed. Like a bounce ease - you don't want to risk the sampling chunks landing on each side of the bounce anchor and having it clipped off.
142
- fast = 0;
143
- }
144
- if (prevPoint.cx < closest) {
145
- if (!prevPoint.cx) {
146
- prevPoint.cx = 0.001; //avoids math problems in getRatio() (dividing by zero)
147
- if (i === l - 1) { //in case the final segment goes vertical RIGHT at the end, make sure we end at the end.
148
- prevPoint.x -= 0.001;
149
- closest = Math.min(closest, 0.001);
150
- fast = 0;
151
- }
152
- } else {
153
- closest = prevPoint.cx;
154
- }
155
- }
156
- } else {
157
- points.splice(i--, 1);
158
- l--;
159
- }
160
- }
161
- l = (1 / closest + 1) | 0;
162
- inc = 1 / l;
163
- j = 0;
164
- point = points[0];
165
- if (fast) {
166
- for (i = 0; i < l; i++) { //for fastest lookups, we just sample along the path at equal x (time) distance. Uses more memory and is slightly less accurate for anchors that don't land on the sampling points, but for the vast majority of eases it's excellent (and fast).
167
- p = i * inc;
168
- if (point.nx < p) {
169
- point = points[++j];
170
- }
171
- a1 = point.y + ((p - point.x) / point.cx) * point.cy;
172
- lookup[i] = {x: p, cx: inc, y: a1, cy: 0, nx: 9};
173
- if (i) {
174
- lookup[i - 1].cy = a1 - lookup[i - 1].y;
175
- }
176
- }
177
- lookup[l - 1].cy = points[points.length - 1].y - a1;
178
- } else { //this option is more accurate, ensuring that EVERY anchor is hit perfectly. Clipping across a bounce, for example, would never happen.
179
- for (i = 0; i < l; i++) { //build a lookup table based on the smallest distance so that we can instantly find the appropriate point (well, it'll either be that point or the very next one). We'll look up based on the linear progress. So it's it's 0.5 and the lookup table has 100 elements, it'd be like lookup[Math.floor(0.5 * 100)]
180
- if (point.nx < i * inc) {
181
- point = points[++j];
182
- }
183
- lookup[i] = point;
184
- }
185
-
186
- if (j < points.length - 1) {
187
- lookup[i-1] = points[points.length-2];
188
- }
189
- }
190
- //this._calcEnd = (points[points.length-1].y !== 1 || points[0].y !== 0); //ensures that we don't run into floating point errors. As long as we're starting at 0 and ending at 1, tell GSAP to skip the final calculation and use 0/1 as the factor.
191
-
192
- this.ease = p => {
193
- let point = lookup[(p * l) | 0] || lookup[l - 1];
194
- if (point.nx < p) {
195
- point = point.n;
196
- }
197
- return point.y + ((p - point.x) / point.cx) * point.cy;
198
- };
199
-
200
- this.ease.custom = this;
201
-
202
- this.id && gsap && gsap.registerEase(this.id, this.ease);
203
-
204
- return this;
205
- }
206
-
207
- getSVGData(config) {
208
- return CustomEase.getSVGData(this, config);
209
- }
210
-
211
- static create(id, data, config) {
212
- return (new CustomEase(id, data, config)).ease;
213
- }
214
-
215
- static register(core) {
216
- gsap = core;
217
- _initCore();
218
- }
219
-
220
- static get(id) {
221
- return gsap.parseEase(id);
222
- }
223
-
224
- static getSVGData(ease, config) {
225
- config = config || {};
226
- let width = config.width || 100,
227
- height = config.height || 100,
228
- x = config.x || 0,
229
- y = (config.y || 0) + height,
230
- e = gsap.utils.toArray(config.path)[0],
231
- a, slope, i, inc, tx, ty, precision, threshold, prevX, prevY;
232
- if (config.invert) {
233
- height = -height;
234
- y = 0;
235
- }
236
- if (typeof(ease) === "string") {
237
- ease = gsap.parseEase(ease);
238
- }
239
- if (ease.custom) {
240
- ease = ease.custom;
241
- }
242
- if (ease instanceof CustomEase) {
243
- a = rawPathToString(transformRawPath([ease.segment], width, 0, 0, -height, x, y));
244
- } else {
245
- a = [x, y];
246
- precision = Math.max(5, (config.precision || 1) * 200);
247
- inc = 1 / precision;
248
- precision += 2;
249
- threshold = 5 / precision;
250
- prevX = _round(x + inc * width);
251
- prevY = _round(y + ease(inc) * -height);
252
- slope = (prevY - y) / (prevX - x);
253
- for (i = 2; i < precision; i++) {
254
- tx = _round(x + i * inc * width);
255
- ty = _round(y + ease(i * inc) * -height);
256
- if (Math.abs((ty - prevY) / (tx - prevX) - slope) > threshold || i === precision - 1) { //only add points when the slope changes beyond the threshold
257
- a.push(prevX, prevY);
258
- slope = (ty - prevY) / (tx - prevX);
259
- }
260
- prevX = tx;
261
- prevY = ty;
262
- }
263
- a = "M" + a.join(",");
264
- }
265
- e && e.setAttribute("d", a);
266
- return a;
267
- }
268
-
269
- }
270
-
271
- _getGSAP() && gsap.registerPlugin(CustomEase);
272
-
273
- CustomEase.version = "3.12.5";
274
-
275
- export { CustomEase as default };