@linear_non/stellar-libs 1.0.6 → 1.0.8

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/README.md CHANGED
@@ -1,14 +1,15 @@
1
1
  # stellar-libs
2
2
 
3
- A collection of lightweight, reusable frontend UI behavior modules — built to work seamlessly with [`stellar-kit`](https://www.npmjs.com/package/@linear_non/stellar-kit) and the [Stellar](https://github.com/nonlinearstudio/stellar) frontend system. Each library is self-contained, configurable, and designed to be dropped into modular websites.
3
+ A collection of lightweight, reusable frontend UI behavior modules — built to work seamlessly with [`stellar-kit`](https://www.npmjs.com/package/@linear_non/stellar-kit) and the [Stellar](https://github.com/nonlinearstudio/stellar) frontend system. Each library is self-contained, configurable, and designed to be dropped into modular websites. Also is a project that is constantly growing and we are adding new updates all the time.
4
4
 
5
- ## ✨ Features
5
+ ## ✨ Avalible Libs
6
6
 
7
+ - Designed for plug-and-play
7
8
  - **Sticky**: Basic sticky logic for DOM elements
8
- - **SplitOnScroll**: Text splitting + reveal synced to scroll
9
9
  - **Smooth**: Smooth scroll instance using Virtual Scroll
10
- - Designed for plug-and-play usage inside Stellar Template
11
- - Works with `kitStore`, `Resize`, `Scroll`, `Raf`, and GSAP if needed
10
+ - **SplitOnScroll**: Text splitting + reveal synced to scroll
11
+ - **Noise**: Configurable canvas noise
12
+ - **SpritePlayer**: Canvas image sequence player
12
13
 
13
14
  ## 📦 Installation
14
15
 
@@ -16,7 +17,7 @@ A collection of lightweight, reusable frontend UI behavior modules — built to
16
17
  npm install @linear_non/stellar-libs
17
18
  ```
18
19
 
19
- > Note: Some libraries rely on `stellar-kit` for shared events, scroll, or utilities. Be sure to install both if needed:
20
+ > Note: Most libraries rely on `stellar-kit` for shared events, scroll, or utilities. Be sure to install both:
20
21
 
21
22
  ```bash
22
23
  npm install @linear_non/stellar-kit
@@ -31,6 +32,8 @@ stellar-libs/
31
32
  │ ├── SplitOnScroll/ # Scroll-triggered text reveals
32
33
  │ ├── Smooth/ # Smooth scrolling system
33
34
  │ └── ScrollBar/ # Custom scrollbar component
35
+ │ └── Noise/ # Canvas noise
36
+ │ └── SpritePlayer/ # Image sprite player
34
37
  ├── dev/ # Dev playgrounds for each lib
35
38
  ├── index.js # Entry point for exports
36
39
  └── vite.config.js # Vite config to run individual demos
@@ -48,12 +51,12 @@ npm run dev
48
51
  ## 🛠️ Usage Example
49
52
 
50
53
  ```js
51
- import { Sticky } from "@linear_non/stellar-libs";
54
+ import { Sticky } from "@linear_non/stellar-libs"
52
55
 
53
56
  const sticky = new Sticky({
54
57
  el: qs(".sticky"),
55
58
  sticky: qs(".sticky-content"),
56
- });
59
+ })
57
60
  ```
58
61
 
59
62
  > You can find usage examples in each library’s README file also an HTML markup example. You can see a live example inside the `dev/` folder.
@@ -62,10 +65,7 @@ const sticky = new Sticky({
62
65
 
63
66
  ### ✅ TODO
64
67
 
65
- - [ ] Implement `Marquee` module
66
- - [ ] Implement `Dropdown` module
67
- - [ ] Implement `Lenis` scroll
68
- - [ ] Update Readme files for each component
68
+ This is a projects that will continue growing and we have plan to add as many things that we feel can be helpful for us in the future.
69
69
 
70
70
  ---
71
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linear_non/stellar-libs",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
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": "^1.1.0"
28
+ "@linear_non/stellar-kit": "^1.1.7"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@linear_non/prettier-config": "^1.0.6",
@@ -77,7 +77,7 @@ export default class Noise {
77
77
  this.ctx?.clearRect(0, 0, this.canvas.width, this.canvas.height)
78
78
  }
79
79
 
80
- resize() {
80
+ resize = () => {
81
81
  const { sizes } = kitStore || {}
82
82
  const vw = sizes?.vw || window.innerWidth
83
83
  const vh = sizes?.vh || window.innerHeight
@@ -0,0 +1,152 @@
1
+ // SpritePlayer.js
2
+ import { ImageLoader } from "@linear_non/stellar-kit/classes"
3
+ import { emitter, EVENTS } from "@linear_non/stellar-kit/events"
4
+ import { sniffer, bounds } from "@linear_non/stellar-kit/utils"
5
+ import { gsap } from "@linear_non/stellar-kit/gsap"
6
+
7
+ export default class SpritePlayer {
8
+ constructor({
9
+ canvas,
10
+ container,
11
+ mobile_path,
12
+ desktop_path,
13
+ fileName,
14
+ total = 0,
15
+ progress = 0,
16
+ fileExtension = "png",
17
+ cache = null, // optional Map for global cache
18
+ persistent = false, // true if using shared cache (don’t revoke)
19
+ }) {
20
+ const rect = bounds(container)
21
+ this.progress = progress
22
+ this.persistent = persistent
23
+
24
+ this.dom = { container, reference: container, images: [] }
25
+ this.canvas = {
26
+ el: canvas,
27
+ ctx: canvas.getContext("2d"),
28
+ width: rect.width,
29
+ height: rect.height,
30
+ rect,
31
+ }
32
+
33
+ this.settings = {
34
+ mobile_path,
35
+ desktop_path,
36
+ file_name: fileName,
37
+ total,
38
+ file_extension: fileExtension,
39
+ cache,
40
+ }
41
+
42
+ this.state = { loaded: false }
43
+ this.isVisible = true
44
+ this.init()
45
+ }
46
+
47
+ async loadImages() {
48
+ const { mobile_path, desktop_path, total, file_name, file_extension, cache } = this.settings
49
+ const origin = sniffer.isDesktop ? desktop_path : mobile_path
50
+
51
+ const loader = new ImageLoader({
52
+ origin,
53
+ fileName: file_name,
54
+ extension: file_extension,
55
+ total,
56
+ cache, // pass cache Map if you have one
57
+ useWorker: true,
58
+ })
59
+
60
+ // (optional) forward progress
61
+ const onProgress = e => emitter.emit("sprite:progress", { instance: this, ...e })
62
+ emitter.on(ImageLoader.events.PROGRESS, onProgress)
63
+
64
+ const images = await loader.load() // ✅ get images from promise
65
+
66
+ emitter.off?.(ImageLoader.events.PROGRESS, onProgress)
67
+
68
+ this.dom.images = images
69
+ this.frameCount = images.length
70
+ this.state.loaded = true
71
+ emitter.emit("sprite:loaded", this)
72
+ }
73
+
74
+ configureCanvas() {
75
+ const { container, reference } = this.dom
76
+ const rect = bounds(container)
77
+ const area = bounds(reference)
78
+ const offset = area.top - rect.top
79
+ const dpr = window.devicePixelRatio || 1
80
+
81
+ const { el, ctx } = this.canvas
82
+ el.style.width = `${rect.width}px`
83
+ el.style.height = `${rect.height}px`
84
+ el.width = Math.floor(rect.width * dpr)
85
+ el.height = Math.floor(rect.height * dpr)
86
+ ctx.setTransform(1, 0, 0, 1, 0, 0)
87
+ ctx.scale(dpr, dpr)
88
+
89
+ Object.assign(this.canvas, { width: rect.width, height: rect.height, rect, area, offset })
90
+ }
91
+
92
+ drawImageCover(ctx, img, area, offset) {
93
+ const iw = img.naturalWidth,
94
+ ih = img.naturalHeight
95
+ const cw = area.width,
96
+ ch = area.height
97
+ const ir = iw / ih,
98
+ cr = cw / ch
99
+ let sw, sh, sx, sy
100
+ if (ir > cr) {
101
+ sh = ih
102
+ sw = ih * cr
103
+ sx = (iw - sw) / 2
104
+ sy = 0
105
+ } else {
106
+ sw = iw
107
+ sh = iw / cr
108
+ sx = 0
109
+ sy = (ih - sh) / 2
110
+ }
111
+ ctx.drawImage(img, sx, sy, sw, sh, 0, offset, cw, ch)
112
+ }
113
+
114
+ tick = ({ current }) => {
115
+ if (!this.state.loaded || !this.isVisible) return
116
+ this.scroll = current
117
+
118
+ const { ctx, width, height, area, offset } = this.canvas
119
+ const { images } = this.dom
120
+ const total = this.frameCount || images.length || 1
121
+ const val = gsap.utils.clamp(0, total - 1, this.progress * total)
122
+ const index = Math.floor(val)
123
+ const img = images[index]
124
+
125
+ ctx.clearRect(0, 0, width, height)
126
+ if (img) this.drawImageCover(ctx, img, area, offset)
127
+ }
128
+
129
+ resize = () => this.configureCanvas()
130
+
131
+ on() {
132
+ emitter.on(EVENTS.APP_TICK, this.tick)
133
+ emitter.on(EVENTS.APP_RESIZE, this.resize)
134
+ }
135
+ off() {
136
+ emitter.off(EVENTS.APP_TICK, this.tick)
137
+ emitter.off(EVENTS.APP_RESIZE, this.resize)
138
+ }
139
+
140
+ destroy() {
141
+ this.off()
142
+ // Only revoke if not using shared cache
143
+ if (!this.persistent) this.dom.images.forEach(img => URL.revokeObjectURL(img?.src))
144
+ this.dom.images = []
145
+ }
146
+
147
+ async init() {
148
+ await this.loadImages()
149
+ this.configureCanvas()
150
+ this.on()
151
+ }
152
+ }
@@ -38,7 +38,7 @@ export default class Sticky {
38
38
  scrub: true,
39
39
  onEnter: () => this.toggleSticky(true),
40
40
  onEnterBack: () => this.toggleSticky(true),
41
- onLeave: () => this.toggleSticky(false, true), // ✅ Ensure totalHeight is passed
41
+ onLeave: () => this.toggleSticky(false, true),
42
42
  onLeaveBack: () => this.toggleSticky(false),
43
43
  onUpdate: self => this.onUpdate(self),
44
44
  })
package/src/index.js CHANGED
@@ -2,5 +2,6 @@ import Sticky from "./Sticky"
2
2
  import Smooth from "./Smooth"
3
3
  import SplitonScroll from "./SplitOnScroll"
4
4
  import Noise from "./Noise"
5
+ import SpritePlayer from "./SpritePlayer"
5
6
 
6
- export { Sticky, Smooth, SplitonScroll, Noise }
7
+ export { Sticky, Smooth, SplitonScroll, Noise, SpritePlayer }