@linear_non/stellar-libs 1.0.29 → 1.0.30

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linear_non/stellar-libs",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
4
4
  "description": "Reusable JavaScript libraries for Non-Linear Studio projects.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -1,20 +1,21 @@
1
- import { splitText, reverseSplit, Observer } from "@linear_non/stellar-kit/plugins"
2
- import { EVENTS } from "@linear_non/stellar-kit/events"
3
- import { ScrollTrigger } from "@linear_non/stellar-kit/gsap"
1
+ import { EVENTS } from "../events"
2
+ import Observer from "./_Observer"
3
+ import { reverseSplit, splitText } from "./_SplitText"
4
4
 
5
5
  export default class SplitonScroll {
6
6
  constructor({
7
- el,
7
+ trigger: el,
8
8
  splitText,
9
9
  isReady,
10
10
  reverse,
11
- start = "top bottom", // "top top+=100%",
12
- end = "bottom top", // "bottom bottom-=100%",
11
+ start = "top bottom",
12
+ end = "bottom top",
13
13
  scrub = false,
14
14
  once = true,
15
15
  }) {
16
16
  this.element = el
17
17
 
18
+ // Normalize split targets to an array
18
19
  if (!splitText) {
19
20
  this.targets = []
20
21
  } else if (splitText instanceof Element) {
@@ -25,17 +26,63 @@ export default class SplitonScroll {
25
26
  this.targets = Array.from(splitText)
26
27
  }
27
28
 
28
- if (!this.targets.length) return
29
-
29
+ // SplitText() instance
30
30
  this.splits = null
31
- this.isReadyCallback = isReady || (() => {})
31
+
32
+ // Grouped SplitText() instances from data-split-group
33
+ this.groups = null
34
+
35
+ // Backward-compatible isReady wrapper
36
+ // isReady(splits) OR isReady(splits, groups) OR isReady({ splits, groups })
37
+ this._userReady = typeof isReady === "function" ? isReady : null
38
+ this.isReadyCallback = (splits, groups) => {
39
+ if (!this._userReady) return
40
+
41
+ if (this._userReady.length === 0) {
42
+ // If callback expects 0 args, give it the object
43
+ this._userReady({ splits, groups })
44
+ } else if (this._userReady.length === 1) {
45
+ // If callback expects 1 arg, assume old-style: isReady(splits)
46
+ this._userReady(splits)
47
+ } else {
48
+ // 2+ args: new-style: isReady(splits, groups)
49
+ this._userReady(splits, groups)
50
+ }
51
+ }
52
+
32
53
  this.reverseCallback = reverse || (() => {})
33
54
  this.start = start
34
55
  this.end = end
35
56
  this.scrub = scrub
36
57
  this.once = once
37
58
 
59
+ // Expose a Promise so users can wait for ready event
60
+ this._resolveReady = null
61
+ this.ready = new Promise(resolve => {
62
+ this._resolveReady = resolve
63
+ })
64
+
65
+ // If no element or no targets, resolve immediately
66
+ if (!this.element || !this.targets.length) {
67
+ const splits = []
68
+ const groups = {}
69
+ const payload = { splits, groups }
70
+
71
+ if (this._resolveReady) {
72
+ this._resolveReady(payload)
73
+ this._resolveReady = null
74
+ }
75
+
76
+ this.isReadyCallback(splits, groups)
77
+ return
78
+ }
79
+
38
80
  this.addObserver()
81
+
82
+ // If already in view, trigger enter handler
83
+ if (this.observer.isActive || this.observer.progress > 0) {
84
+ this.handleEnter()
85
+ }
39
86
  }
40
87
 
41
88
  addObserver() {
@@ -53,18 +100,32 @@ export default class SplitonScroll {
53
100
 
54
101
  async handleEnter() {
55
102
  if (this.splits) {
56
- this.isReadyCallback(this.splits)
103
+ this.isReadyCallback(this.splits, this.groups || {})
57
104
  return
58
105
  }
59
106
 
60
- const split = splitText(this.targets)
61
- const splits = await new Promise(resolve => {
62
- split.on(EVENTS.APP_SPLITTEXT_READY, readySplits => {
63
- resolve(readySplits)
107
+ const emitter = splitText(this.targets)
108
+
109
+ const { splits, groups } = await new Promise(resolve => {
110
+ emitter.on(EVENTS.APP_SPLITTEXT_READY, (readySplits, groupMap) => {
111
+ resolve({
112
+ splits: readySplits || [],
113
+ groups: groupMap || {},
114
+ })
64
115
  })
65
116
  })
117
+
66
118
  this.splits = splits
67
- this.isReadyCallback(splits)
119
+ this.groups = groups
120
+
121
+ const payload = { splits, groups }
122
+
123
+ if (this._resolveReady) {
124
+ this._resolveReady(payload)
125
+ this._resolveReady = null
126
+ }
127
+
128
+ this.isReadyCallback(splits, groups)
68
129
  }
69
130
 
70
131
  handleLeave() {
@@ -86,6 +147,7 @@ export default class SplitonScroll {
86
147
  destroy() {
87
148
  this.observer?.kill()
88
149
  this.splits = null
150
+ this.groups = null
89
151
  this.targets = null
90
152
  this.element = null
91
153
  }