@nightshadeui/scroller 2.16.0

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.
@@ -0,0 +1,16 @@
1
+ import type { ScrollerParams } from './types.js';
2
+ export declare class ScrollerController {
3
+ readonly params: ScrollerParams;
4
+ private el;
5
+ private frame;
6
+ private state;
7
+ private onScroll;
8
+ constructor(params?: ScrollerParams);
9
+ get t(): number;
10
+ mount(el: HTMLElement): void;
11
+ unmount(): void;
12
+ update(): void;
13
+ private updateNow;
14
+ private computeT;
15
+ }
16
+ //# sourceMappingURL=ScrollerController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollerController.d.ts","sourceRoot":"","sources":["../src/ScrollerController.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,qBAAa,kBAAkB;IAWvB,QAAQ,CAAC,MAAM,EAAE,cAAc;IATnC,OAAO,CAAC,EAAE,CAA4B;IACtC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,KAAK,CAEV;IAEH,OAAO,CAAC,QAAQ,CAAuB;gBAG1B,MAAM,GAAE,cAAmB;IAGxC,IAAI,CAAC,WAEJ;IAED,KAAK,CAAC,EAAE,EAAE,WAAW;IAMrB,OAAO;IAMP,MAAM;IAKN,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,QAAQ;CAkBnB"}
@@ -0,0 +1,48 @@
1
+ import { reactive } from 'vue';
2
+ export class ScrollerController {
3
+ constructor(params = {}) {
4
+ this.params = params;
5
+ this.el = null;
6
+ this.frame = 0;
7
+ this.state = reactive({
8
+ t: 0,
9
+ });
10
+ this.onScroll = () => this.update();
11
+ }
12
+ get t() {
13
+ return this.state.t;
14
+ }
15
+ mount(el) {
16
+ this.el = el;
17
+ window.addEventListener('scroll', this.onScroll, { passive: true });
18
+ this.update();
19
+ }
20
+ unmount() {
21
+ this.el = null;
22
+ window.removeEventListener('scroll', this.onScroll);
23
+ cancelAnimationFrame(this.frame);
24
+ }
25
+ update() {
26
+ cancelAnimationFrame(this.frame);
27
+ this.frame = requestAnimationFrame(() => this.updateNow());
28
+ }
29
+ updateNow() {
30
+ if (!this.el) {
31
+ return;
32
+ }
33
+ this.state.t = this.computeT(this.el);
34
+ }
35
+ computeT(el) {
36
+ const { start = 0, end = 1, startAnchor = 'top', endAnchor = 'bottom', } = this.params;
37
+ const h = window.innerHeight;
38
+ const rect = el.getBoundingClientRect();
39
+ const startAnchorY = startAnchor === 'top' ? rect.top : rect.top + rect.height;
40
+ const endAnchorY = endAnchor === 'top' ? rect.top : rect.top + rect.height;
41
+ const startY = startAnchorY - h * (1 - start);
42
+ const endY = endAnchorY - h * (1 - end);
43
+ const extent = endY - startY;
44
+ const t = (0 - startY) / extent;
45
+ return Math.min(1, Math.max(0, t));
46
+ }
47
+ }
48
+ //# sourceMappingURL=ScrollerController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ScrollerController.js","sourceRoot":"","sources":["../src/ScrollerController.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAI/B,MAAM,OAAO,kBAAkB;IAU3B,YACa,SAAyB,EAAE;QAA3B,WAAM,GAAN,MAAM,CAAqB;QAThC,OAAE,GAAuB,IAAI,CAAC;QAC9B,UAAK,GAAG,CAAC,CAAC;QACV,UAAK,GAAG,QAAQ,CAAC;YACrB,CAAC,EAAE,CAAC;SACP,CAAC,CAAC;QAEK,aAAQ,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;IAIpC,CAAC;IAEJ,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,EAAe;QACjB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,EAAE,CAAC;IAClB,CAAC;IAED,OAAO;QACH,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC;QACf,MAAM,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC;IAED,MAAM;QACF,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IAC/D,CAAC;IAEO,SAAS;QACb,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACX,OAAO;QACX,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;IAEO,QAAQ,CAAC,EAAe;QAC5B,MAAM,EACF,KAAK,GAAG,CAAC,EACT,GAAG,GAAG,CAAC,EACP,WAAW,GAAG,KAAK,EACnB,SAAS,GAAG,QAAQ,GACvB,GAAG,IAAI,CAAC,MAAM,CAAC;QAChB,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,CAAC,qBAAqB,EAAE,CAAC;QACxC,MAAM,YAAY,GAAG,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;QAC/E,MAAM,UAAU,GAAG,SAAS,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3E,MAAM,MAAM,GAAG,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,UAAU,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;QAC7B,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;CAEJ"}
package/out/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './ScrollerController.js';
2
+ export * from './types.js';
3
+ export * from './useScroller.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
package/out/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from './ScrollerController.js';
2
+ export * from './types.js';
3
+ export * from './useScroller.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC"}
package/out/types.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ export type ScrollerAnchor = 'top' | 'bottom';
2
+ export interface ScrollerParams {
3
+ start?: number;
4
+ end?: number;
5
+ startAnchor?: ScrollerAnchor;
6
+ endAnchor?: ScrollerAnchor;
7
+ }
8
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE9C,MAAM,WAAW,cAAc;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,SAAS,CAAC,EAAE,cAAc,CAAC;CAC9B"}
package/out/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { ScrollerParams } from './types.js';
2
+ export declare function useScroller(params?: ScrollerParams): {
3
+ t: import("vue").Ref<number, number>;
4
+ scrollerEl: import("vue").Ref<HTMLElement | null, HTMLElement | null>;
5
+ updateScroller: () => void;
6
+ };
7
+ //# sourceMappingURL=useScroller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScroller.d.ts","sourceRoot":"","sources":["../src/useScroller.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,wBAAgB,WAAW,CAAC,MAAM,GAAE,cAAmB;;;;EAkBtD"}
@@ -0,0 +1,22 @@
1
+ import { onMounted, onUnmounted, ref, toRef } from 'vue';
2
+ import { ScrollerController } from './ScrollerController.js';
3
+ export function useScroller(params = {}) {
4
+ const scrollerEl = ref(null);
5
+ const scroller = new ScrollerController(params);
6
+ onMounted(() => {
7
+ const el = scrollerEl.value;
8
+ if (!el) {
9
+ return;
10
+ }
11
+ scroller.mount(el);
12
+ });
13
+ onUnmounted(() => {
14
+ scroller.unmount();
15
+ });
16
+ return {
17
+ t: toRef(scroller, 't'),
18
+ scrollerEl,
19
+ updateScroller: () => scroller.update(),
20
+ };
21
+ }
22
+ //# sourceMappingURL=useScroller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScroller.js","sourceRoot":"","sources":["../src/useScroller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC;AAEzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,MAAM,UAAU,WAAW,CAAC,SAAyB,EAAE;IACnD,MAAM,UAAU,GAAG,GAAG,CAAqB,IAAI,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAChD,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,EAAE,EAAE,CAAC;YACN,OAAO;QACX,CAAC;QACD,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IACH,WAAW,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,OAAO,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IACH,OAAO;QACH,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC;QACvB,UAAU;QACV,cAAc,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE;KAC1C,CAAC;AACN,CAAC"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@nightshadeui/scroller",
3
+ "version": "2.16.0",
4
+ "description": "Scroll progress composable for Nightshade Vue apps",
5
+ "author": "Boris Okunskiy",
6
+ "license": "ISC",
7
+ "type": "module",
8
+ "sideEffects": false,
9
+ "exports": {
10
+ ".": {
11
+ "types": "./out/index.d.ts",
12
+ "import": "./out/index.js",
13
+ "default": "./out/index.js"
14
+ },
15
+ "./src": {
16
+ "types": "./src/index.ts",
17
+ "import": "./src/index.ts",
18
+ "default": "./src/index.ts"
19
+ }
20
+ },
21
+ "files": [
22
+ "out",
23
+ "src"
24
+ ],
25
+ "scripts": {
26
+ "build": "tsc -b"
27
+ },
28
+ "peerDependencies": {
29
+ "vue": "^3.5.22"
30
+ }
31
+ }
@@ -0,0 +1,65 @@
1
+ import { reactive } from 'vue';
2
+
3
+ import type { ScrollerParams } from './types.js';
4
+
5
+ export class ScrollerController {
6
+
7
+ private el: HTMLElement | null = null;
8
+ private frame = 0;
9
+ private state = reactive({
10
+ t: 0,
11
+ });
12
+
13
+ private onScroll = () => this.update();
14
+
15
+ constructor(
16
+ readonly params: ScrollerParams = {},
17
+ ) {}
18
+
19
+ get t() {
20
+ return this.state.t;
21
+ }
22
+
23
+ mount(el: HTMLElement) {
24
+ this.el = el;
25
+ window.addEventListener('scroll', this.onScroll, { passive: true });
26
+ this.update();
27
+ }
28
+
29
+ unmount() {
30
+ this.el = null;
31
+ window.removeEventListener('scroll', this.onScroll);
32
+ cancelAnimationFrame(this.frame);
33
+ }
34
+
35
+ update() {
36
+ cancelAnimationFrame(this.frame);
37
+ this.frame = requestAnimationFrame(() => this.updateNow());
38
+ }
39
+
40
+ private updateNow() {
41
+ if (!this.el) {
42
+ return;
43
+ }
44
+ this.state.t = this.computeT(this.el);
45
+ }
46
+
47
+ private computeT(el: HTMLElement) {
48
+ const {
49
+ start = 0,
50
+ end = 1,
51
+ startAnchor = 'top',
52
+ endAnchor = 'bottom',
53
+ } = this.params;
54
+ const h = window.innerHeight;
55
+ const rect = el.getBoundingClientRect();
56
+ const startAnchorY = startAnchor === 'top' ? rect.top : rect.top + rect.height;
57
+ const endAnchorY = endAnchor === 'top' ? rect.top : rect.top + rect.height;
58
+ const startY = startAnchorY - h * (1 - start);
59
+ const endY = endAnchorY - h * (1 - end);
60
+ const extent = endY - startY;
61
+ const t = (0 - startY) / extent;
62
+ return Math.min(1, Math.max(0, t));
63
+ }
64
+
65
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export * from './ScrollerController.js';
2
+ export * from './types.js';
3
+ export * from './useScroller.js';
package/src/types.ts ADDED
@@ -0,0 +1,8 @@
1
+ export type ScrollerAnchor = 'top' | 'bottom';
2
+
3
+ export interface ScrollerParams {
4
+ start?: number;
5
+ end?: number;
6
+ startAnchor?: ScrollerAnchor;
7
+ endAnchor?: ScrollerAnchor;
8
+ }
@@ -0,0 +1,24 @@
1
+ import { onMounted, onUnmounted, ref, toRef } from 'vue';
2
+
3
+ import { ScrollerController } from './ScrollerController.js';
4
+ import type { ScrollerParams } from './types.js';
5
+
6
+ export function useScroller(params: ScrollerParams = {}) {
7
+ const scrollerEl = ref<HTMLElement | null>(null);
8
+ const scroller = new ScrollerController(params);
9
+ onMounted(() => {
10
+ const el = scrollerEl.value;
11
+ if (!el) {
12
+ return;
13
+ }
14
+ scroller.mount(el);
15
+ });
16
+ onUnmounted(() => {
17
+ scroller.unmount();
18
+ });
19
+ return {
20
+ t: toRef(scroller, 't'),
21
+ scrollerEl,
22
+ updateScroller: () => scroller.update(),
23
+ };
24
+ }