@linear_non/stellar-libs 1.0.29 → 1.0.31

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