use-snap-slider 0.0.3 → 0.0.5

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,3 +1,202 @@
1
1
  # use-snap-slider
2
2
 
3
- React hook to manage css snap sliders
3
+ React hook / Vanilla JS to manage scroll-state for [CSS Scroll Snap](https://caniuse.com/?search=scroll-snap)
4
+
5
+ Gives you states and actions for CSS Scroll Snap sliders:
6
+
7
+ * `count:number` - total pages
8
+ * `countDelta:number` - total slides, for 1/1 width slides the same as count
9
+ * `index:number` - current page index
10
+ * `indexDelto:number` - current slide index, for 1/1 width slides the same as index
11
+ * `prevEnabled:boolean` - can go to previous slide
12
+ * `nextEnabled:boolean` - can go to next slide
13
+ * `goPrev()` - scroll to previous slide
14
+ * `goNext()` - scroll to next slide
15
+ * `jumpTo(index:number)` - go to a spesified slide
16
+
17
+ ## Usage
18
+
19
+ `npm i use-snap-slider`
20
+
21
+ ### Basic usage (react)
22
+
23
+ In your react component:
24
+
25
+ See a [more complete react-example here](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/react-example/SnapSliderReact.tsx)
26
+
27
+ ```tsx
28
+ import React, { useRef } from 'react'
29
+ import { useSnapSlider } from 'use-snap-slider'
30
+
31
+ export function MySlider () {
32
+ const ref = useRef<HTMLDivElement | null>(null)
33
+ const slides = [1,2]
34
+ // Passing inital count avoid extra render, for best lighthouse score, pass the same count as you show on mobile
35
+ const {index, count, jumpTo, goPrev, goNext, prevEnabled, nextEnabled} = useSnapSlider(ref, slides.length)
36
+ const pages = Array.from(Array(count).keys())
37
+ return (
38
+ <div>
39
+ <div className="flex scroll-smooth snap-x snap-mandatory overflow-x-auto" ref={ref}>
40
+ {slides.map((slide) => (
41
+ <div key={slide} className="flex snap-start shrink-0 w-full md:w-1/2">
42
+ Slide {slide}
43
+ </div>
44
+ ))}
45
+ </div>
46
+ <nav aria-label="Pages navigation">
47
+ {pages.map((page) => (
48
+ <button onClick={() => jumpTo(page)} disabled={page === index}>{page + 1}</button>
49
+ ))}
50
+ </nav>
51
+ <nav aria-label="Prev / Next navigation">
52
+ <button onClick={goPrev} disabled={!prevEnabled}>Prev</button>
53
+ <button onClick={goNext} disabled={!nextEnabled}>Next</button>
54
+ </nav>
55
+ </div>
56
+ )
57
+ }
58
+ ```
59
+
60
+ ### Basic usage (vanilla javascript)
61
+
62
+ See a [more complete vanilla javascript example here](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/vanilla-example/create-snap-slider.ts)
63
+
64
+ ```ts
65
+ import { createSnapSlider } from 'use-snap-slider/dist/snap-slider'
66
+
67
+ function createSnapSliderVanilla(element: HTMLElement) {
68
+ const { jumpTo, goNext, goPrev, subscribe } = createSnapSlider({
69
+ element,
70
+ count: count,
71
+ index: 0,
72
+ })
73
+ subscribe((state) => {
74
+ // Update UI with sate
75
+ })
76
+ document.querySelector('.prev-btn')?.addEventListener('click', goPrev)
77
+ document.querySelector('.next-btn')?.addEventListener('click', goNext)
78
+ }
79
+ // Expose globally
80
+ window.createSnapSliderVanilla = createSnapSliderVanilla
81
+ ```
82
+
83
+ ## API
84
+
85
+ ### useSnapSlider react hook
86
+
87
+ ```ts
88
+ import { useSnapSlider } from 'use-snap-slider'
89
+
90
+ const {
91
+ index: number,
92
+ // If displaying multiple slides on the same page, this will be slide at left position
93
+ indexDelta: number,
94
+ // Count of pages
95
+ count: number,
96
+ countDelta: number,
97
+ prevEnabled: boolean,
98
+ nextEnabled: boolean,
99
+ jumpTo: (index: number) => void,
100
+ goNext: () => void,
101
+ goPrev: () => void,
102
+ } = useSnapSlider(
103
+ ref: MutableRefObject<HTMLDivElement | null>,
104
+ // Pass inital count
105
+ count?: number = 1,
106
+ // Pass inital index
107
+ index?: number = 0,
108
+ // onPrev / next buttons go to end / start
109
+ circular = false,
110
+ // Will reset index on change of count, but pass something here to force a reset even if count dont change
111
+ countHash?: string | number
112
+ )
113
+ ```
114
+
115
+ ### useSnapSlider react hook
116
+
117
+ ```ts
118
+ import { createSnapSlider } from 'use-snap-slider/dist/snap-slider'
119
+
120
+ const {
121
+ // Removes event listner for window.resize and element.scroll
122
+ destroy: () => void,
123
+ // Get current state
124
+ getState: () => TSnapSliderStateFull,
125
+ // Go to slide index
126
+ jumpTo: (index?: number, indexDelta?: number) => void,
127
+ goNext: () => void,
128
+ goPrev: () => void,
129
+ // Subscribe to updates
130
+ subscribe: (fn: TSnapListner) => () => void,
131
+ // Set element at later stage
132
+ setElement: (el: HTMLElement) => void,
133
+ // Updates count and countDelta, call if you change inner slides
134
+ calculate: () => void,
135
+ // Should subscribe return a inital publish after subscribing
136
+ initalSubscriptionPublish: boolean = true
137
+ } = createSnapSlider({
138
+ element: HTMLDivElement | null,
139
+ count?:number = 1,
140
+ countDelta?:number,
141
+ index?:number = 0,
142
+ circular?:boolean,
143
+ indexDelta?:number,
144
+ itemSelector?:string = ':scope > *',
145
+ })
146
+ ```
147
+
148
+ ## Adding nessesary styles
149
+
150
+ This library only delivers javascript for handle the state, you will need to make your own component for complete solution. See examples in this repo:
151
+
152
+ * [React component](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/react-example/SnapSliderReact.tsx)
153
+ * [Vanilla JS function](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/vanilla-example/create-snap-slider.ts)
154
+
155
+ ### TailwindCSS
156
+
157
+ See also tailwinds own documentation for [scroll snap](https://tailwindcss.com/docs/scroll-snap-type)
158
+
159
+ ```html
160
+ <div class="flex scroll-smooth snap-x snap-mandatory overflow-x-auto">
161
+ <div class="flex snap-start shrink-0">
162
+ Slide 1
163
+ </div>
164
+ <div class="flex snap-start shrink-0">
165
+ Slide 2
166
+ </div>
167
+ </div>
168
+ ```
169
+
170
+ ### Basic css
171
+
172
+ ```html
173
+ <style>
174
+ .css-slider {
175
+ display: flex;
176
+ overflow-x: auto;
177
+ scroll-snap-type: x mandatory;
178
+ scroll-behavior: smooth;
179
+ -webkit-overflow-scrolling: touch;
180
+ }
181
+ .css-slider::-webkit-scrollbar {
182
+ display: none;
183
+ }
184
+ .css-slider-item {
185
+ display: flex;
186
+ scroll-snap-align: start;
187
+ flex-shrink: 0;
188
+ }
189
+ .css-slider-item-half {
190
+ width: 50%;
191
+ }
192
+ </style>
193
+ <!-- Markup -->
194
+ <div class="css-slider">
195
+ <div class="css-slider-item css-slider-item-half">
196
+ Slide 1
197
+ </div>
198
+ <div class="css-slider-item css-slider-item-half">
199
+ Slide 2
200
+ </div>
201
+ </div>
202
+ ```
@@ -26,7 +26,7 @@ export interface TSnapSliderParams extends TSnapSliderStateUpdate {
26
26
  export type TSnapSliderJumpToFn = (index?: number, indexDelta?: number) => void;
27
27
  export interface TSnapSlider {
28
28
  destroy: () => void;
29
- getState: (count?: number, index?: number) => TSnapSliderStateFull;
29
+ getState: () => TSnapSliderStateFull;
30
30
  jumpTo: TSnapSliderJumpToFn;
31
31
  goNext: () => void;
32
32
  goPrev: () => void;
@@ -1 +1 @@
1
- export declare const throttle: (fn: Function, wait?: number) => (this: any) => void;
1
+ export declare const throttle: (fn: Function, wait: number) => (this: any) => void;
@@ -1,5 +1,5 @@
1
- import { MutableRefObject } from "react";
2
- import { TSnapSliderStateFull } from "./snap-slider";
1
+ import { MutableRefObject } from 'react';
2
+ import { TSnapSliderStateFull } from './snap-slider';
3
3
  export interface TUseSnapSlider extends TSnapSliderStateFull {
4
4
  jumpTo: (index: number) => void;
5
5
  goNext: () => void;
@@ -1,241 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const throttle = (fn, wait = 300) => {
4
- let inThrottle, lastFn, lastTime;
5
- return function() {
6
- const context = this, args = arguments;
7
- if (!inThrottle) {
8
- fn.apply(context, args);
9
- lastTime = Date.now();
10
- inThrottle = true;
11
- } else {
12
- clearTimeout(lastFn);
13
- lastFn = setTimeout(() => {
14
- if (Date.now() - lastTime >= wait) {
15
- fn.apply(context, args);
16
- lastTime = Date.now();
17
- }
18
- }, Math.max(wait - (Date.now() - lastTime), 0));
19
- }
20
- };
21
- };
22
- function createSnapSlider({
23
- element: _element,
24
- count = 1,
25
- countDelta,
26
- index = 0,
27
- circular,
28
- indexDelta,
29
- initalSubscriptionPublish = true,
30
- itemSelector = ":scope > *"
31
- }) {
32
- let initalIndex = index;
33
- let state = {
34
- index,
35
- indexDelta: indexDelta || index,
36
- count,
37
- countDelta: countDelta || count
38
- };
39
- let prevIndexDelta = index;
40
- let slidesPerPage = 1;
41
- let itemPositions = [];
42
- let muteScrollListner = false;
43
- let left = 0;
44
- let element;
45
- function updateIndexDelta() {
46
- if (!element) {
47
- return;
48
- }
49
- const prev = element.scrollLeft;
50
- const { indexDelta: indexDelta2 } = state;
51
- left = indexDelta2 * (element.offsetWidth / slidesPerPage);
52
- if (prevIndexDelta !== indexDelta2) {
53
- const distance = Math.abs(prev - left);
54
- const limitInstantScroll = element.offsetWidth * 2;
55
- prevIndexDelta = indexDelta2;
56
- muteScrollListner = true;
57
- element.scroll({
58
- left,
59
- top: 0,
60
- behavior: distance > limitInstantScroll ? "smooth" : void 0
61
- });
62
- } else {
63
- if (initalIndex) {
64
- muteScrollListner = true;
65
- element.scroll({
66
- left,
67
- top: 0
68
- });
69
- initalIndex = void 0;
70
- }
71
- }
72
- }
73
- let listeners = [];
74
- const subscribe = (callback) => {
75
- listeners.push(callback);
76
- return () => {
77
- listeners = listeners.filter((x) => x !== callback);
78
- if (listeners.length < 1) {
79
- destroy();
80
- }
81
- };
82
- };
83
- function notify() {
84
- listeners.forEach((callback) => {
85
- callback(getState());
86
- });
87
- }
88
- const getState = () => {
89
- const { indexDelta: indexDelta2, countDelta: countDelta2 } = state;
90
- return {
91
- ...state,
92
- prevEnabled: circular || indexDelta2 > 0,
93
- nextEnabled: circular || countDelta2 - slidesPerPage > indexDelta2
94
- };
95
- };
96
- let initalPublish = !initalSubscriptionPublish;
97
- function update(params = {}) {
98
- let dirty = false;
99
- let indexDeltaDirty = false;
100
- const keys = Object.keys(
101
- params
102
- );
103
- keys.forEach((key) => {
104
- if (state[key] !== params[key]) {
105
- state[key] = Number(params[key]);
106
- dirty = true;
107
- if (key === "indexDelta") {
108
- indexDeltaDirty = true;
109
- }
110
- }
111
- });
112
- if (dirty || !initalPublish) {
113
- initalPublish = true;
114
- notify();
115
- if (indexDeltaDirty) {
116
- updateIndexDelta();
117
- }
118
- }
119
- }
120
- function fixIndex(nextIndex) {
121
- const { index: index2, indexDelta: indexDelta2 } = nextIndex;
122
- const { countDelta: countDelta2, count: count2 } = state;
123
- const last = countDelta2 - slidesPerPage;
124
- return {
125
- index: indexDelta2 < last ? index2 : count2 - 1,
126
- indexDelta: indexDelta2
127
- };
128
- }
129
- function calculate() {
130
- if (!element) {
131
- return;
132
- }
133
- let contentWidth = 0;
134
- let itemWidth = 0;
135
- itemPositions = [];
136
- element.querySelectorAll(itemSelector).forEach((slide) => {
137
- itemPositions.push(contentWidth);
138
- contentWidth += slide.clientWidth;
139
- itemWidth = slide.clientWidth;
140
- });
141
- slidesPerPage = Math.round(element.offsetWidth / itemWidth);
142
- const count2 = Math.ceil(contentWidth / element.offsetWidth);
143
- const countDelta2 = itemPositions.length;
144
- const { index: index2 } = state;
145
- const resetIndexMayby = index2 + 1 > count2 ? {
146
- index: 0,
147
- indexDelta: 0
148
- } : {};
149
- update({
150
- count: count2,
151
- countDelta: countDelta2,
152
- ...resetIndexMayby
153
- });
154
- }
155
- let ticking = false;
156
- function onScroll() {
157
- if (!ticking && element) {
158
- const scrollLeft = element.scrollLeft;
159
- window.requestAnimationFrame(() => {
160
- if (muteScrollListner) {
161
- const leftToScroll = Math.abs(left - scrollLeft);
162
- if (leftToScroll < 1) {
163
- muteScrollListner = false;
164
- }
165
- } else {
166
- const positionItem = itemPositions.reduce((prev, curr) => {
167
- return Math.abs(curr - scrollLeft) < Math.abs(prev - scrollLeft) ? curr : prev;
168
- });
169
- const indexDelta2 = itemPositions.findIndex((x) => x === positionItem);
170
- prevIndexDelta = indexDelta2;
171
- update(
172
- fixIndex({
173
- index: Math.floor(indexDelta2 / slidesPerPage),
174
- indexDelta: indexDelta2
175
- })
176
- );
177
- }
178
- ticking = false;
179
- });
180
- ticking = true;
181
- }
182
- }
183
- const onScrollFn = throttle(onScroll, 200);
184
- const onResizeFn = throttle(calculate, 200);
185
- function setElement(_el) {
186
- if (element) {
187
- destroy();
188
- }
189
- element = _el;
190
- updateIndexDelta();
191
- calculate();
192
- element == null ? void 0 : element.addEventListener("scroll", onScrollFn);
193
- window.addEventListener("resize", onResizeFn);
194
- }
195
- _element && setElement(_element);
196
- const jumpTo = function(index2, indexDelta2) {
197
- if (indexDelta2 !== void 0) {
198
- update(
199
- fixIndex({
200
- index: Math.floor(indexDelta2 / slidesPerPage),
201
- indexDelta: indexDelta2
202
- })
203
- );
204
- }
205
- if (index2 !== void 0) {
206
- update(
207
- fixIndex({
208
- index: index2,
209
- indexDelta: index2 * slidesPerPage
210
- })
211
- );
212
- }
213
- };
214
- const destroy = () => {
215
- element == null ? void 0 : element.removeEventListener("scroll", onScrollFn);
216
- window.removeEventListener("resize", onResizeFn);
217
- };
218
- const goNext = () => {
219
- const { countDelta: countDelta2, indexDelta: indexDelta2 } = state;
220
- const last = countDelta2 - slidesPerPage;
221
- const next = indexDelta2 + slidesPerPage <= last ? indexDelta2 + slidesPerPage : circular && indexDelta2 === last ? 0 : last;
222
- jumpTo(void 0, next);
223
- };
224
- const goPrev = () => {
225
- const { indexDelta: indexDelta2, countDelta: countDelta2 } = state;
226
- const last = countDelta2 - slidesPerPage;
227
- const next = indexDelta2 - slidesPerPage >= 0 ? indexDelta2 - slidesPerPage : circular && indexDelta2 === 0 ? last : 0;
228
- jumpTo(void 0, next);
229
- };
230
- return {
231
- destroy,
232
- getState,
233
- subscribe,
234
- jumpTo,
235
- setElement,
236
- calculate,
237
- goNext,
238
- goPrev
239
- };
240
- }
241
- exports.createSnapSlider = createSnapSlider;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const q=(f,u)=>{let h,r,a;return function(){const v=this,p=arguments;h?(clearTimeout(r),r=setTimeout(()=>{Date.now()-a>=u&&(f.apply(v,p),a=Date.now())},Math.max(u-(Date.now()-a),0))):(f.apply(v,p),a=Date.now(),h=!0)}};function C({element:f,count:u=1,countDelta:h,index:r=0,circular:a,indexDelta:v,initalSubscriptionPublish:p=!0,itemSelector:A=":scope > *"}){let T=r,c={index:r,indexDelta:v||r,count:u,countDelta:h||u},m=r,i=1,D=[],b=!1,x=0,n;function W(){if(n){const t=n.scrollLeft,{indexDelta:e}=c;if(x=e*(n.offsetWidth/i),m!==e){const o=Math.abs(t-x),l=n.offsetWidth*2;m=e,b=!0;const s=o>l?"instant":"smooth";n.scroll({left:x,top:0,behavior:s})}else T&&(b=!0,n.scroll({left:x,top:0,behavior:"instant"}),T=void 0)}}let P=!1,d=[];const O=t=>(d.push(t),n&&(P||p)&&t(S()),()=>{d=d.filter(e=>e!==t),d.length<1&&I()});function R(){d.forEach(t=>{t(S())})}const S=()=>{const{indexDelta:t,countDelta:e}=c;return{...c,prevEnabled:a||t>0,nextEnabled:a||e-i>t}};function g(t){let e=!1,o=!1;Object.keys(t).forEach(s=>{c[s]!==t[s]&&(c[s]=Number(t[s]),e=!0,s==="indexDelta"&&(o=!0))}),e&&(P=d.length===0,R(),o&&W())}function y(t){const{index:e,indexDelta:o}=t,{countDelta:l,count:s}=c,L=l-i;return{index:o<L?e:s-1,indexDelta:o}}function M(){if(n){let t=0,e=0;D=[],n.querySelectorAll(A).forEach(N=>{D.push(t),t+=N.clientWidth,e=N.clientWidth}),i=Math.round(n.offsetWidth/e);const o=D.length,l=Math.ceil(o/i),{index:s}=c,L=s+1>l?{index:0,indexDelta:0}:{};g({count:l,countDelta:o,...L})}}let E=!1;function B(){if(!E&&n){const t=n.scrollLeft;window.requestAnimationFrame(()=>{if(b)Math.abs(x-t)<2&&(b=!1);else{const e=D.reduce((l,s)=>Math.abs(s-t)<Math.abs(l-t)?s:l),o=D.findIndex(l=>l===e);m=o,g(y({index:Math.floor(o/i),indexDelta:o}))}E=!1}),E=!0}}const F=q(B,200),j=q(M,500);function z(t){n&&I(),n=t,W(),M(),n==null||n.addEventListener("scroll",F),window.addEventListener("resize",j)}f&&z(f);const w=function(t,e){e!==void 0&&g(y({index:Math.floor(e/i),indexDelta:e})),t!==void 0&&g(y({index:t,indexDelta:t*i}))},I=()=>{n==null||n.removeEventListener("scroll",F),window.removeEventListener("resize",j)};return{destroy:I,getState:S,subscribe:O,jumpTo:w,setElement:z,calculate:M,goNext:()=>{const{countDelta:t,indexDelta:e}=c,o=t-i,l=e+i<=o?e+i:a&&e===o?0:o;w(void 0,l)},goPrev:()=>{const{indexDelta:t,countDelta:e}=c,o=e-i,l=t-i>=0?t-i:a&&t===0?o:0;w(void 0,l)}}}exports.createSnapSlider=C;
2
+ //# sourceMappingURL=snap-slider.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap-slider.cjs.js","sources":["../src/lib/throttle.ts","../src/lib/snap-slider.ts"],"sourcesContent":["export const throttle = (fn: Function, wait: number) => {\n let inThrottle: boolean\n let lastFn: ReturnType<typeof setTimeout>\n let lastTime: number\n return function (this: any) {\n const context = this\n const args = arguments\n if (!inThrottle) {\n fn.apply(context, args)\n lastTime = Date.now()\n inThrottle = true\n } else {\n clearTimeout(lastFn)\n lastFn = setTimeout(() => {\n if (Date.now() - lastTime >= wait) {\n fn.apply(context, args)\n lastTime = Date.now()\n }\n }, Math.max(wait - (Date.now() - lastTime), 0))\n }\n }\n}\n","import { throttle } from './throttle'\n\nexport interface TSnapListnerStateIndex {\n index: number\n indexDelta: number\n}\n\nexport interface TSnapSliderState extends TSnapListnerStateIndex {\n count: number\n countDelta: number\n}\n\ninterface TSnapSliderStateUpdate {\n index?: number\n indexDelta?: number\n count?: number\n countDelta?: number\n}\n\nexport interface TSnapSliderStateFull extends TSnapSliderState {\n prevEnabled: boolean\n nextEnabled: boolean\n}\n\nexport type TSnapListner = (params: TSnapSliderStateFull) => void\n\nexport interface TSnapSliderParams extends TSnapSliderStateUpdate {\n element: HTMLElement | null\n itemSelector?: string\n initalSubscriptionPublish?: boolean\n circular?: boolean\n}\n\nexport type TSnapSliderJumpToFn = (index?: number, indexDelta?: number) => void\n\nexport interface TSnapSlider {\n destroy: () => void\n getState: () => TSnapSliderStateFull\n jumpTo: TSnapSliderJumpToFn\n goNext: () => void\n goPrev: () => void\n subscribe: (fn: TSnapListner) => () => void\n setElement: (el: HTMLElement) => void\n calculate: () => void\n}\n\nexport function createSnapSlider({\n element: _element,\n count = 1,\n countDelta,\n index = 0,\n circular,\n indexDelta,\n initalSubscriptionPublish = true,\n itemSelector = ':scope > *',\n}: TSnapSliderParams): TSnapSlider {\n let initalIndex: number | undefined = index\n let state: TSnapSliderState = {\n index,\n indexDelta: indexDelta || index,\n count,\n countDelta: countDelta || count,\n }\n let prevIndexDelta: number = index\n let slidesPerPage: number = 1\n let itemPositions: number[] = []\n let muteScrollListner: boolean = false\n let left: number = 0\n let element: HTMLElement | null\n function updateIndexDelta() {\n if (element) {\n const prev = element.scrollLeft\n const { indexDelta } = state\n left = indexDelta * (element.offsetWidth / slidesPerPage)\n if (prevIndexDelta !== indexDelta) {\n const distance = Math.abs(prev - left)\n const limitInstantScroll = element.offsetWidth * 2\n prevIndexDelta = indexDelta\n muteScrollListner = true\n // @ts-expect-error [mildly irritated message]\n const behavior: ScrollBehavior =\n distance > limitInstantScroll ? 'instant' : 'smooth'\n element.scroll({\n left,\n top: 0,\n behavior,\n })\n } else {\n if (initalIndex) {\n muteScrollListner = true\n element.scroll({\n left,\n top: 0,\n // @ts-expect-error [mildly irritated message]\n behavior: 'instant',\n })\n initalIndex = undefined\n }\n }\n }\n }\n\n let publishDirty = false\n let listeners: TSnapListner[] = []\n const subscribe = (callback: TSnapListner) => {\n listeners.push(callback)\n if (element && (publishDirty || initalSubscriptionPublish)) {\n callback(getState())\n }\n return () => {\n listeners = listeners.filter((x) => x !== callback)\n if (listeners.length < 1) {\n destroy()\n }\n }\n }\n function notify() {\n listeners.forEach((callback) => {\n callback(getState())\n })\n }\n const getState = (): TSnapSliderStateFull => {\n const { indexDelta, countDelta } = state\n return {\n ...state,\n prevEnabled: circular || indexDelta > 0,\n nextEnabled: circular || countDelta - slidesPerPage > indexDelta,\n }\n }\n function update(params: TSnapSliderStateUpdate) {\n let dirty = false\n let indexDeltaDirty = false\n type TSnapSliderStateUpdateKey = keyof typeof params\n const keys: TSnapSliderStateUpdateKey[] = Object.keys(\n params\n ) as Array<TSnapSliderStateUpdateKey>\n keys.forEach((key) => {\n if (state[key] !== params[key]) {\n state[key] = Number(params[key])\n dirty = true\n if (key === 'indexDelta') {\n indexDeltaDirty = true\n }\n }\n })\n if (dirty) {\n publishDirty = listeners.length === 0\n notify()\n if (indexDeltaDirty) {\n updateIndexDelta()\n }\n }\n }\n function fixIndex(nextIndex: TSnapListnerStateIndex): TSnapListnerStateIndex {\n const { index, indexDelta } = nextIndex\n const { countDelta, count } = state\n const last = countDelta - slidesPerPage\n return {\n index: indexDelta < last ? index : count - 1,\n indexDelta,\n }\n }\n function calculate() {\n if (element) {\n let contentWidth = 0\n let itemWidth = 0\n itemPositions = []\n element.querySelectorAll(itemSelector).forEach((slide) => {\n itemPositions.push(contentWidth)\n contentWidth += slide.clientWidth\n itemWidth = slide.clientWidth\n })\n slidesPerPage = Math.round(element.offsetWidth / itemWidth)\n const countDelta = itemPositions.length\n const count = Math.ceil(countDelta / slidesPerPage)\n const { index } = state\n const resetIndexMayby =\n index + 1 > count\n ? {\n index: 0,\n indexDelta: 0,\n }\n : {}\n update({\n count,\n countDelta,\n ...resetIndexMayby,\n })\n }\n }\n\n let ticking = false\n function onScroll() {\n if (!ticking && element) {\n const scrollLeft = element.scrollLeft\n window.requestAnimationFrame(() => {\n if (muteScrollListner) {\n const leftToScroll = Math.abs(left - scrollLeft)\n if (leftToScroll < 2) {\n muteScrollListner = false\n }\n } else {\n const positionItem = itemPositions.reduce((prev, curr) => {\n return Math.abs(curr - scrollLeft) < Math.abs(prev - scrollLeft)\n ? curr\n : prev\n })\n const indexDelta = itemPositions.findIndex((x) => x === positionItem)\n prevIndexDelta = indexDelta\n update(\n fixIndex({\n index: Math.floor(indexDelta / slidesPerPage),\n indexDelta,\n })\n )\n }\n ticking = false\n })\n ticking = true\n }\n }\n const onScrollFn = throttle(onScroll, 200)\n const onResizeFn = throttle(calculate, 500)\n function setElement(_el: HTMLElement) {\n if (element) {\n destroy()\n }\n element = _el\n updateIndexDelta()\n calculate()\n element?.addEventListener('scroll', onScrollFn)\n window.addEventListener('resize', onResizeFn)\n }\n _element && setElement(_element)\n const jumpTo: TSnapSliderJumpToFn = function (index, indexDelta) {\n if (indexDelta !== undefined) {\n update(\n fixIndex({\n index: Math.floor(indexDelta / slidesPerPage),\n indexDelta,\n })\n )\n }\n if (index !== undefined) {\n update(\n fixIndex({\n index,\n indexDelta: index * slidesPerPage,\n })\n )\n }\n }\n const destroy = () => {\n element?.removeEventListener('scroll', onScrollFn)\n window.removeEventListener('resize', onResizeFn)\n }\n const goNext = () => {\n const { countDelta, indexDelta } = state\n const last = countDelta - slidesPerPage\n const next =\n indexDelta + slidesPerPage <= last\n ? indexDelta + slidesPerPage\n : circular && indexDelta === last\n ? 0\n : last\n jumpTo(undefined, next)\n }\n const goPrev = () => {\n const { indexDelta, countDelta } = state\n const last = countDelta - slidesPerPage\n const next =\n indexDelta - slidesPerPage >= 0\n ? indexDelta - slidesPerPage\n : circular && indexDelta === 0\n ? last\n : 0\n jumpTo(undefined, next)\n }\n return {\n destroy,\n getState,\n subscribe,\n jumpTo,\n setElement,\n calculate,\n goNext,\n goPrev,\n }\n}\n"],"names":["throttle","fn","wait","inThrottle","lastFn","lastTime","context","args","createSnapSlider","_element","count","countDelta","index","circular","indexDelta","initalSubscriptionPublish","itemSelector","initalIndex","state","prevIndexDelta","slidesPerPage","itemPositions","muteScrollListner","left","element","updateIndexDelta","prev","distance","limitInstantScroll","behavior","publishDirty","listeners","subscribe","callback","getState","x","destroy","notify","update","params","dirty","indexDeltaDirty","key","fixIndex","nextIndex","last","calculate","contentWidth","itemWidth","slide","resetIndexMayby","ticking","onScroll","scrollLeft","positionItem","curr","onScrollFn","onResizeFn","setElement","_el","jumpTo","next"],"mappings":"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"}
@@ -1,241 +1,156 @@
1
- const throttle = (fn, wait = 300) => {
2
- let inThrottle, lastFn, lastTime;
1
+ const q = (f, u) => {
2
+ let h, r, c;
3
3
  return function() {
4
- const context = this, args = arguments;
5
- if (!inThrottle) {
6
- fn.apply(context, args);
7
- lastTime = Date.now();
8
- inThrottle = true;
9
- } else {
10
- clearTimeout(lastFn);
11
- lastFn = setTimeout(() => {
12
- if (Date.now() - lastTime >= wait) {
13
- fn.apply(context, args);
14
- lastTime = Date.now();
15
- }
16
- }, Math.max(wait - (Date.now() - lastTime), 0));
17
- }
4
+ const v = this, p = arguments;
5
+ h ? (clearTimeout(r), r = setTimeout(() => {
6
+ Date.now() - c >= u && (f.apply(v, p), c = Date.now());
7
+ }, Math.max(u - (Date.now() - c), 0))) : (f.apply(v, p), c = Date.now(), h = !0);
18
8
  };
19
9
  };
20
- function createSnapSlider({
21
- element: _element,
22
- count = 1,
23
- countDelta,
24
- index = 0,
25
- circular,
26
- indexDelta,
27
- initalSubscriptionPublish = true,
28
- itemSelector = ":scope > *"
10
+ function H({
11
+ element: f,
12
+ count: u = 1,
13
+ countDelta: h,
14
+ index: r = 0,
15
+ circular: c,
16
+ indexDelta: v,
17
+ initalSubscriptionPublish: p = !0,
18
+ itemSelector: A = ":scope > *"
29
19
  }) {
30
- let initalIndex = index;
31
- let state = {
32
- index,
33
- indexDelta: indexDelta || index,
34
- count,
35
- countDelta: countDelta || count
36
- };
37
- let prevIndexDelta = index;
38
- let slidesPerPage = 1;
39
- let itemPositions = [];
40
- let muteScrollListner = false;
41
- let left = 0;
42
- let element;
43
- function updateIndexDelta() {
44
- if (!element) {
45
- return;
46
- }
47
- const prev = element.scrollLeft;
48
- const { indexDelta: indexDelta2 } = state;
49
- left = indexDelta2 * (element.offsetWidth / slidesPerPage);
50
- if (prevIndexDelta !== indexDelta2) {
51
- const distance = Math.abs(prev - left);
52
- const limitInstantScroll = element.offsetWidth * 2;
53
- prevIndexDelta = indexDelta2;
54
- muteScrollListner = true;
55
- element.scroll({
56
- left,
57
- top: 0,
58
- behavior: distance > limitInstantScroll ? "smooth" : void 0
59
- });
60
- } else {
61
- if (initalIndex) {
62
- muteScrollListner = true;
63
- element.scroll({
64
- left,
65
- top: 0
20
+ let T = r, a = {
21
+ index: r,
22
+ indexDelta: v || r,
23
+ count: u,
24
+ countDelta: h || u
25
+ }, g = r, i = 1, x = [], m = !1, D = 0, n;
26
+ function W() {
27
+ if (n) {
28
+ const t = n.scrollLeft, { indexDelta: e } = a;
29
+ if (D = e * (n.offsetWidth / i), g !== e) {
30
+ const o = Math.abs(t - D), l = n.offsetWidth * 2;
31
+ g = e, m = !0;
32
+ const s = o > l ? "instant" : "smooth";
33
+ n.scroll({
34
+ left: D,
35
+ top: 0,
36
+ behavior: s
66
37
  });
67
- initalIndex = void 0;
68
- }
38
+ } else
39
+ T && (m = !0, n.scroll({
40
+ left: D,
41
+ top: 0,
42
+ // @ts-expect-error [mildly irritated message]
43
+ behavior: "instant"
44
+ }), T = void 0);
69
45
  }
70
46
  }
71
- let listeners = [];
72
- const subscribe = (callback) => {
73
- listeners.push(callback);
74
- return () => {
75
- listeners = listeners.filter((x) => x !== callback);
76
- if (listeners.length < 1) {
77
- destroy();
78
- }
79
- };
80
- };
81
- function notify() {
82
- listeners.forEach((callback) => {
83
- callback(getState());
47
+ let P = !1, d = [];
48
+ const O = (t) => (d.push(t), n && (P || p) && t(E()), () => {
49
+ d = d.filter((e) => e !== t), d.length < 1 && I();
50
+ });
51
+ function R() {
52
+ d.forEach((t) => {
53
+ t(E());
84
54
  });
85
55
  }
86
- const getState = () => {
87
- const { indexDelta: indexDelta2, countDelta: countDelta2 } = state;
56
+ const E = () => {
57
+ const { indexDelta: t, countDelta: e } = a;
88
58
  return {
89
- ...state,
90
- prevEnabled: circular || indexDelta2 > 0,
91
- nextEnabled: circular || countDelta2 - slidesPerPage > indexDelta2
59
+ ...a,
60
+ prevEnabled: c || t > 0,
61
+ nextEnabled: c || e - i > t
92
62
  };
93
63
  };
94
- let initalPublish = !initalSubscriptionPublish;
95
- function update(params = {}) {
96
- let dirty = false;
97
- let indexDeltaDirty = false;
98
- const keys = Object.keys(
99
- params
100
- );
101
- keys.forEach((key) => {
102
- if (state[key] !== params[key]) {
103
- state[key] = Number(params[key]);
104
- dirty = true;
105
- if (key === "indexDelta") {
106
- indexDeltaDirty = true;
107
- }
108
- }
109
- });
110
- if (dirty || !initalPublish) {
111
- initalPublish = true;
112
- notify();
113
- if (indexDeltaDirty) {
114
- updateIndexDelta();
115
- }
116
- }
64
+ function b(t) {
65
+ let e = !1, o = !1;
66
+ Object.keys(
67
+ t
68
+ ).forEach((s) => {
69
+ a[s] !== t[s] && (a[s] = Number(t[s]), e = !0, s === "indexDelta" && (o = !0));
70
+ }), e && (P = d.length === 0, R(), o && W());
117
71
  }
118
- function fixIndex(nextIndex) {
119
- const { index: index2, indexDelta: indexDelta2 } = nextIndex;
120
- const { countDelta: countDelta2, count: count2 } = state;
121
- const last = countDelta2 - slidesPerPage;
72
+ function M(t) {
73
+ const { index: e, indexDelta: o } = t, { countDelta: l, count: s } = a, L = l - i;
122
74
  return {
123
- index: indexDelta2 < last ? index2 : count2 - 1,
124
- indexDelta: indexDelta2
75
+ index: o < L ? e : s - 1,
76
+ indexDelta: o
125
77
  };
126
78
  }
127
- function calculate() {
128
- if (!element) {
129
- return;
79
+ function S() {
80
+ if (n) {
81
+ let t = 0, e = 0;
82
+ x = [], n.querySelectorAll(A).forEach((j) => {
83
+ x.push(t), t += j.clientWidth, e = j.clientWidth;
84
+ }), i = Math.round(n.offsetWidth / e);
85
+ const o = x.length, l = Math.ceil(o / i), { index: s } = a, L = s + 1 > l ? {
86
+ index: 0,
87
+ indexDelta: 0
88
+ } : {};
89
+ b({
90
+ count: l,
91
+ countDelta: o,
92
+ ...L
93
+ });
130
94
  }
131
- let contentWidth = 0;
132
- let itemWidth = 0;
133
- itemPositions = [];
134
- element.querySelectorAll(itemSelector).forEach((slide) => {
135
- itemPositions.push(contentWidth);
136
- contentWidth += slide.clientWidth;
137
- itemWidth = slide.clientWidth;
138
- });
139
- slidesPerPage = Math.round(element.offsetWidth / itemWidth);
140
- const count2 = Math.ceil(contentWidth / element.offsetWidth);
141
- const countDelta2 = itemPositions.length;
142
- const { index: index2 } = state;
143
- const resetIndexMayby = index2 + 1 > count2 ? {
144
- index: 0,
145
- indexDelta: 0
146
- } : {};
147
- update({
148
- count: count2,
149
- countDelta: countDelta2,
150
- ...resetIndexMayby
151
- });
152
95
  }
153
- let ticking = false;
154
- function onScroll() {
155
- if (!ticking && element) {
156
- const scrollLeft = element.scrollLeft;
96
+ let w = !1;
97
+ function B() {
98
+ if (!w && n) {
99
+ const t = n.scrollLeft;
157
100
  window.requestAnimationFrame(() => {
158
- if (muteScrollListner) {
159
- const leftToScroll = Math.abs(left - scrollLeft);
160
- if (leftToScroll < 1) {
161
- muteScrollListner = false;
162
- }
163
- } else {
164
- const positionItem = itemPositions.reduce((prev, curr) => {
165
- return Math.abs(curr - scrollLeft) < Math.abs(prev - scrollLeft) ? curr : prev;
166
- });
167
- const indexDelta2 = itemPositions.findIndex((x) => x === positionItem);
168
- prevIndexDelta = indexDelta2;
169
- update(
170
- fixIndex({
171
- index: Math.floor(indexDelta2 / slidesPerPage),
172
- indexDelta: indexDelta2
101
+ if (m)
102
+ Math.abs(D - t) < 2 && (m = !1);
103
+ else {
104
+ const e = x.reduce((l, s) => Math.abs(s - t) < Math.abs(l - t) ? s : l), o = x.findIndex((l) => l === e);
105
+ g = o, b(
106
+ M({
107
+ index: Math.floor(o / i),
108
+ indexDelta: o
173
109
  })
174
110
  );
175
111
  }
176
- ticking = false;
177
- });
178
- ticking = true;
112
+ w = !1;
113
+ }), w = !0;
179
114
  }
180
115
  }
181
- const onScrollFn = throttle(onScroll, 200);
182
- const onResizeFn = throttle(calculate, 200);
183
- function setElement(_el) {
184
- if (element) {
185
- destroy();
186
- }
187
- element = _el;
188
- updateIndexDelta();
189
- calculate();
190
- element == null ? void 0 : element.addEventListener("scroll", onScrollFn);
191
- window.addEventListener("resize", onResizeFn);
116
+ const F = q(B, 200), z = q(S, 500);
117
+ function N(t) {
118
+ n && I(), n = t, W(), S(), n == null || n.addEventListener("scroll", F), window.addEventListener("resize", z);
192
119
  }
193
- _element && setElement(_element);
194
- const jumpTo = function(index2, indexDelta2) {
195
- if (indexDelta2 !== void 0) {
196
- update(
197
- fixIndex({
198
- index: Math.floor(indexDelta2 / slidesPerPage),
199
- indexDelta: indexDelta2
200
- })
201
- );
202
- }
203
- if (index2 !== void 0) {
204
- update(
205
- fixIndex({
206
- index: index2,
207
- indexDelta: index2 * slidesPerPage
208
- })
209
- );
210
- }
211
- };
212
- const destroy = () => {
213
- element == null ? void 0 : element.removeEventListener("scroll", onScrollFn);
214
- window.removeEventListener("resize", onResizeFn);
215
- };
216
- const goNext = () => {
217
- const { countDelta: countDelta2, indexDelta: indexDelta2 } = state;
218
- const last = countDelta2 - slidesPerPage;
219
- const next = indexDelta2 + slidesPerPage <= last ? indexDelta2 + slidesPerPage : circular && indexDelta2 === last ? 0 : last;
220
- jumpTo(void 0, next);
221
- };
222
- const goPrev = () => {
223
- const { indexDelta: indexDelta2, countDelta: countDelta2 } = state;
224
- const last = countDelta2 - slidesPerPage;
225
- const next = indexDelta2 - slidesPerPage >= 0 ? indexDelta2 - slidesPerPage : circular && indexDelta2 === 0 ? last : 0;
226
- jumpTo(void 0, next);
120
+ f && N(f);
121
+ const y = function(t, e) {
122
+ e !== void 0 && b(
123
+ M({
124
+ index: Math.floor(e / i),
125
+ indexDelta: e
126
+ })
127
+ ), t !== void 0 && b(
128
+ M({
129
+ index: t,
130
+ indexDelta: t * i
131
+ })
132
+ );
133
+ }, I = () => {
134
+ n == null || n.removeEventListener("scroll", F), window.removeEventListener("resize", z);
227
135
  };
228
136
  return {
229
- destroy,
230
- getState,
231
- subscribe,
232
- jumpTo,
233
- setElement,
234
- calculate,
235
- goNext,
236
- goPrev
137
+ destroy: I,
138
+ getState: E,
139
+ subscribe: O,
140
+ jumpTo: y,
141
+ setElement: N,
142
+ calculate: S,
143
+ goNext: () => {
144
+ const { countDelta: t, indexDelta: e } = a, o = t - i, l = e + i <= o ? e + i : c && e === o ? 0 : o;
145
+ y(void 0, l);
146
+ },
147
+ goPrev: () => {
148
+ const { indexDelta: t, countDelta: e } = a, o = e - i, l = t - i >= 0 ? t - i : c && t === 0 ? o : 0;
149
+ y(void 0, l);
150
+ }
237
151
  };
238
152
  }
239
153
  export {
240
- createSnapSlider
154
+ H as createSnapSlider
241
155
  };
156
+ //# sourceMappingURL=snap-slider.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap-slider.es.js","sources":["../src/lib/throttle.ts","../src/lib/snap-slider.ts"],"sourcesContent":["export const throttle = (fn: Function, wait: number) => {\n let inThrottle: boolean\n let lastFn: ReturnType<typeof setTimeout>\n let lastTime: number\n return function (this: any) {\n const context = this\n const args = arguments\n if (!inThrottle) {\n fn.apply(context, args)\n lastTime = Date.now()\n inThrottle = true\n } else {\n clearTimeout(lastFn)\n lastFn = setTimeout(() => {\n if (Date.now() - lastTime >= wait) {\n fn.apply(context, args)\n lastTime = Date.now()\n }\n }, Math.max(wait - (Date.now() - lastTime), 0))\n }\n }\n}\n","import { throttle } from './throttle'\n\nexport interface TSnapListnerStateIndex {\n index: number\n indexDelta: number\n}\n\nexport interface TSnapSliderState extends TSnapListnerStateIndex {\n count: number\n countDelta: number\n}\n\ninterface TSnapSliderStateUpdate {\n index?: number\n indexDelta?: number\n count?: number\n countDelta?: number\n}\n\nexport interface TSnapSliderStateFull extends TSnapSliderState {\n prevEnabled: boolean\n nextEnabled: boolean\n}\n\nexport type TSnapListner = (params: TSnapSliderStateFull) => void\n\nexport interface TSnapSliderParams extends TSnapSliderStateUpdate {\n element: HTMLElement | null\n itemSelector?: string\n initalSubscriptionPublish?: boolean\n circular?: boolean\n}\n\nexport type TSnapSliderJumpToFn = (index?: number, indexDelta?: number) => void\n\nexport interface TSnapSlider {\n destroy: () => void\n getState: () => TSnapSliderStateFull\n jumpTo: TSnapSliderJumpToFn\n goNext: () => void\n goPrev: () => void\n subscribe: (fn: TSnapListner) => () => void\n setElement: (el: HTMLElement) => void\n calculate: () => void\n}\n\nexport function createSnapSlider({\n element: _element,\n count = 1,\n countDelta,\n index = 0,\n circular,\n indexDelta,\n initalSubscriptionPublish = true,\n itemSelector = ':scope > *',\n}: TSnapSliderParams): TSnapSlider {\n let initalIndex: number | undefined = index\n let state: TSnapSliderState = {\n index,\n indexDelta: indexDelta || index,\n count,\n countDelta: countDelta || count,\n }\n let prevIndexDelta: number = index\n let slidesPerPage: number = 1\n let itemPositions: number[] = []\n let muteScrollListner: boolean = false\n let left: number = 0\n let element: HTMLElement | null\n function updateIndexDelta() {\n if (element) {\n const prev = element.scrollLeft\n const { indexDelta } = state\n left = indexDelta * (element.offsetWidth / slidesPerPage)\n if (prevIndexDelta !== indexDelta) {\n const distance = Math.abs(prev - left)\n const limitInstantScroll = element.offsetWidth * 2\n prevIndexDelta = indexDelta\n muteScrollListner = true\n // @ts-expect-error [mildly irritated message]\n const behavior: ScrollBehavior =\n distance > limitInstantScroll ? 'instant' : 'smooth'\n element.scroll({\n left,\n top: 0,\n behavior,\n })\n } else {\n if (initalIndex) {\n muteScrollListner = true\n element.scroll({\n left,\n top: 0,\n // @ts-expect-error [mildly irritated message]\n behavior: 'instant',\n })\n initalIndex = undefined\n }\n }\n }\n }\n\n let publishDirty = false\n let listeners: TSnapListner[] = []\n const subscribe = (callback: TSnapListner) => {\n listeners.push(callback)\n if (element && (publishDirty || initalSubscriptionPublish)) {\n callback(getState())\n }\n return () => {\n listeners = listeners.filter((x) => x !== callback)\n if (listeners.length < 1) {\n destroy()\n }\n }\n }\n function notify() {\n listeners.forEach((callback) => {\n callback(getState())\n })\n }\n const getState = (): TSnapSliderStateFull => {\n const { indexDelta, countDelta } = state\n return {\n ...state,\n prevEnabled: circular || indexDelta > 0,\n nextEnabled: circular || countDelta - slidesPerPage > indexDelta,\n }\n }\n function update(params: TSnapSliderStateUpdate) {\n let dirty = false\n let indexDeltaDirty = false\n type TSnapSliderStateUpdateKey = keyof typeof params\n const keys: TSnapSliderStateUpdateKey[] = Object.keys(\n params\n ) as Array<TSnapSliderStateUpdateKey>\n keys.forEach((key) => {\n if (state[key] !== params[key]) {\n state[key] = Number(params[key])\n dirty = true\n if (key === 'indexDelta') {\n indexDeltaDirty = true\n }\n }\n })\n if (dirty) {\n publishDirty = listeners.length === 0\n notify()\n if (indexDeltaDirty) {\n updateIndexDelta()\n }\n }\n }\n function fixIndex(nextIndex: TSnapListnerStateIndex): TSnapListnerStateIndex {\n const { index, indexDelta } = nextIndex\n const { countDelta, count } = state\n const last = countDelta - slidesPerPage\n return {\n index: indexDelta < last ? index : count - 1,\n indexDelta,\n }\n }\n function calculate() {\n if (element) {\n let contentWidth = 0\n let itemWidth = 0\n itemPositions = []\n element.querySelectorAll(itemSelector).forEach((slide) => {\n itemPositions.push(contentWidth)\n contentWidth += slide.clientWidth\n itemWidth = slide.clientWidth\n })\n slidesPerPage = Math.round(element.offsetWidth / itemWidth)\n const countDelta = itemPositions.length\n const count = Math.ceil(countDelta / slidesPerPage)\n const { index } = state\n const resetIndexMayby =\n index + 1 > count\n ? {\n index: 0,\n indexDelta: 0,\n }\n : {}\n update({\n count,\n countDelta,\n ...resetIndexMayby,\n })\n }\n }\n\n let ticking = false\n function onScroll() {\n if (!ticking && element) {\n const scrollLeft = element.scrollLeft\n window.requestAnimationFrame(() => {\n if (muteScrollListner) {\n const leftToScroll = Math.abs(left - scrollLeft)\n if (leftToScroll < 2) {\n muteScrollListner = false\n }\n } else {\n const positionItem = itemPositions.reduce((prev, curr) => {\n return Math.abs(curr - scrollLeft) < Math.abs(prev - scrollLeft)\n ? curr\n : prev\n })\n const indexDelta = itemPositions.findIndex((x) => x === positionItem)\n prevIndexDelta = indexDelta\n update(\n fixIndex({\n index: Math.floor(indexDelta / slidesPerPage),\n indexDelta,\n })\n )\n }\n ticking = false\n })\n ticking = true\n }\n }\n const onScrollFn = throttle(onScroll, 200)\n const onResizeFn = throttle(calculate, 500)\n function setElement(_el: HTMLElement) {\n if (element) {\n destroy()\n }\n element = _el\n updateIndexDelta()\n calculate()\n element?.addEventListener('scroll', onScrollFn)\n window.addEventListener('resize', onResizeFn)\n }\n _element && setElement(_element)\n const jumpTo: TSnapSliderJumpToFn = function (index, indexDelta) {\n if (indexDelta !== undefined) {\n update(\n fixIndex({\n index: Math.floor(indexDelta / slidesPerPage),\n indexDelta,\n })\n )\n }\n if (index !== undefined) {\n update(\n fixIndex({\n index,\n indexDelta: index * slidesPerPage,\n })\n )\n }\n }\n const destroy = () => {\n element?.removeEventListener('scroll', onScrollFn)\n window.removeEventListener('resize', onResizeFn)\n }\n const goNext = () => {\n const { countDelta, indexDelta } = state\n const last = countDelta - slidesPerPage\n const next =\n indexDelta + slidesPerPage <= last\n ? indexDelta + slidesPerPage\n : circular && indexDelta === last\n ? 0\n : last\n jumpTo(undefined, next)\n }\n const goPrev = () => {\n const { indexDelta, countDelta } = state\n const last = countDelta - slidesPerPage\n const next =\n indexDelta - slidesPerPage >= 0\n ? indexDelta - slidesPerPage\n : circular && indexDelta === 0\n ? last\n : 0\n jumpTo(undefined, next)\n }\n return {\n destroy,\n getState,\n subscribe,\n jumpTo,\n setElement,\n calculate,\n goNext,\n goPrev,\n }\n}\n"],"names":["throttle","fn","wait","inThrottle","lastFn","lastTime","context","args","createSnapSlider","_element","count","countDelta","index","circular","indexDelta","initalSubscriptionPublish","itemSelector","initalIndex","state","prevIndexDelta","slidesPerPage","itemPositions","muteScrollListner","left","element","updateIndexDelta","prev","distance","limitInstantScroll","behavior","publishDirty","listeners","subscribe","callback","getState","x","destroy","notify","update","params","dirty","indexDeltaDirty","key","fixIndex","nextIndex","last","calculate","contentWidth","itemWidth","slide","resetIndexMayby","ticking","onScroll","scrollLeft","positionItem","curr","onScrollFn","onResizeFn","setElement","_el","jumpTo","next"],"mappings":"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"}
@@ -1,45 +1,2 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
4
- const snapSlider = require("./snap-slider.cjs.js");
5
- function useSnapSlider(ref, count = 1, index = 0, circular = false, countHash) {
6
- const [, forceUpdate] = react.useState(0);
7
- const mountedRef = react.useRef();
8
- const [observer] = react.useState(
9
- () => snapSlider.createSnapSlider({
10
- element: ref.current,
11
- count,
12
- index,
13
- circular,
14
- initalSubscriptionPublish: false
15
- })
16
- );
17
- const result = observer.getState(count, index);
18
- react.useEffect(() => {
19
- if (mountedRef.current) {
20
- console.log("change count", count, countHash);
21
- observer.jumpTo(0);
22
- observer.calculate();
23
- }
24
- }, [count, countHash, observer]);
25
- react.useEffect(() => {
26
- mountedRef.current = true;
27
- const unsubscribe = observer.subscribe(() => {
28
- if (mountedRef.current) {
29
- forceUpdate((x) => x + 1);
30
- }
31
- });
32
- ref.current && observer.setElement(ref.current);
33
- return () => {
34
- mountedRef.current = false;
35
- unsubscribe();
36
- };
37
- }, [observer, forceUpdate]);
38
- return {
39
- ...result,
40
- jumpTo: observer.jumpTo,
41
- goNext: observer.goNext,
42
- goPrev: observer.goPrev
43
- };
44
- }
45
- exports.useSnapSlider = useSnapSlider;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react"),f=require("./snap-slider.cjs.js");function p(u,n=1,c=0,o=!1,i){const[,s]=t.useState(0),r=t.useRef(),[e]=t.useState(()=>f.createSnapSlider({element:u.current,count:n,index:c,circular:o,initalSubscriptionPublish:!1})),a=e.getState();return t.useEffect(()=>{r.current&&(e.jumpTo(0),e.calculate())},[n,i,e]),t.useEffect(()=>{r.current=!0,u.current&&e.setElement(u.current);const l=e.subscribe(()=>{r.current&&s(S=>S+1)});return()=>{r.current=!1,l()}},[e,s]),{...a,jumpTo:e.jumpTo,goNext:e.goNext,goPrev:e.goPrev}}exports.useSnapSlider=p;
2
+ //# sourceMappingURL=use-snap-slider.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-snap-slider.cjs.js","sources":["../src/lib/use-snap-slider.ts"],"sourcesContent":["import { MutableRefObject, useEffect, useRef, useState } from 'react'\nimport { createSnapSlider, TSnapSliderStateFull } from './snap-slider'\n\nexport interface TUseSnapSlider extends TSnapSliderStateFull {\n jumpTo: (index: number) => void\n goNext: () => void\n goPrev: () => void\n}\n\nexport function useSnapSlider(\n ref: MutableRefObject<HTMLDivElement | null>,\n count: number = 1,\n index: number = 0,\n circular = false,\n countHash?: string | number\n): TUseSnapSlider {\n const [, forceUpdate] = useState<number>(0)\n const mountedRef = useRef<boolean>()\n const [observer] = useState(() =>\n createSnapSlider({\n element: ref.current,\n count,\n index,\n circular,\n initalSubscriptionPublish: false,\n })\n )\n const result = observer.getState()\n useEffect(() => {\n if (mountedRef.current) {\n observer.jumpTo(0)\n observer.calculate()\n }\n }, [count, countHash, observer])\n useEffect(() => {\n mountedRef.current = true\n ref.current && observer.setElement(ref.current)\n const unsubscribe = observer.subscribe(() => {\n if (mountedRef.current) {\n forceUpdate((x) => x + 1)\n }\n })\n\n return () => {\n mountedRef.current = false\n unsubscribe()\n }\n }, [observer, forceUpdate])\n return {\n ...result,\n jumpTo: observer.jumpTo,\n goNext: observer.goNext,\n goPrev: observer.goPrev,\n }\n}\n"],"names":["useSnapSlider","ref","count","index","circular","countHash","forceUpdate","useState","mountedRef","useRef","observer","createSnapSlider","result","useEffect","unsubscribe","x"],"mappings":"2IASgB,SAAAA,EACdC,EACAC,EAAgB,EAChBC,EAAgB,EAChBC,EAAW,GACXC,EACgB,CAChB,KAAM,EAAGC,CAAW,EAAIC,WAAiB,CAAC,EACpCC,EAAaC,EAAAA,SACb,CAACC,CAAQ,EAAIH,EAAA,SAAS,IAC1BI,mBAAiB,CACf,QAASV,EAAI,QACb,MAAAC,EACA,MAAAC,EACA,SAAAC,EACA,0BAA2B,EAAA,CAC5B,CAAA,EAEGQ,EAASF,EAAS,WACxBG,OAAAA,EAAAA,UAAU,IAAM,CACVL,EAAW,UACbE,EAAS,OAAO,CAAC,EACjBA,EAAS,UAAU,EAEpB,EAAA,CAACR,EAAOG,EAAWK,CAAQ,CAAC,EAC/BG,EAAAA,UAAU,IAAM,CACdL,EAAW,QAAU,GACrBP,EAAI,SAAWS,EAAS,WAAWT,EAAI,OAAO,EACxC,MAAAa,EAAcJ,EAAS,UAAU,IAAM,CACvCF,EAAW,SACDF,EAACS,GAAMA,EAAI,CAAC,CAC1B,CACD,EAED,MAAO,IAAM,CACXP,EAAW,QAAU,GACTM,GAAA,CACd,EACC,CAACJ,EAAUJ,CAAW,CAAC,EACnB,CACL,GAAGM,EACH,OAAQF,EAAS,OACjB,OAAQA,EAAS,OACjB,OAAQA,EAAS,MAAA,CAErB"}
@@ -1,45 +1,33 @@
1
- import { useState, useRef, useEffect } from "react";
2
- import { createSnapSlider } from "./snap-slider.es.js";
3
- function useSnapSlider(ref, count = 1, index = 0, circular = false, countHash) {
4
- const [, forceUpdate] = useState(0);
5
- const mountedRef = useRef();
6
- const [observer] = useState(
7
- () => createSnapSlider({
8
- element: ref.current,
9
- count,
10
- index,
11
- circular,
12
- initalSubscriptionPublish: false
1
+ import { useState as o, useRef as p, useEffect as s } from "react";
2
+ import { createSnapSlider as b } from "./snap-slider.es.js";
3
+ function d(r, u = 1, c = 0, i = !1, a) {
4
+ const [, n] = o(0), t = p(), [e] = o(
5
+ () => b({
6
+ element: r.current,
7
+ count: u,
8
+ index: c,
9
+ circular: i,
10
+ initalSubscriptionPublish: !1
13
11
  })
14
- );
15
- const result = observer.getState(count, index);
16
- useEffect(() => {
17
- if (mountedRef.current) {
18
- console.log("change count", count, countHash);
19
- observer.jumpTo(0);
20
- observer.calculate();
21
- }
22
- }, [count, countHash, observer]);
23
- useEffect(() => {
24
- mountedRef.current = true;
25
- const unsubscribe = observer.subscribe(() => {
26
- if (mountedRef.current) {
27
- forceUpdate((x) => x + 1);
28
- }
12
+ ), l = e.getState();
13
+ return s(() => {
14
+ t.current && (e.jumpTo(0), e.calculate());
15
+ }, [u, a, e]), s(() => {
16
+ t.current = !0, r.current && e.setElement(r.current);
17
+ const f = e.subscribe(() => {
18
+ t.current && n((m) => m + 1);
29
19
  });
30
- ref.current && observer.setElement(ref.current);
31
20
  return () => {
32
- mountedRef.current = false;
33
- unsubscribe();
21
+ t.current = !1, f();
34
22
  };
35
- }, [observer, forceUpdate]);
36
- return {
37
- ...result,
38
- jumpTo: observer.jumpTo,
39
- goNext: observer.goNext,
40
- goPrev: observer.goPrev
23
+ }, [e, n]), {
24
+ ...l,
25
+ jumpTo: e.jumpTo,
26
+ goNext: e.goNext,
27
+ goPrev: e.goPrev
41
28
  };
42
29
  }
43
30
  export {
44
- useSnapSlider
31
+ d as useSnapSlider
45
32
  };
33
+ //# sourceMappingURL=use-snap-slider.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-snap-slider.es.js","sources":["../src/lib/use-snap-slider.ts"],"sourcesContent":["import { MutableRefObject, useEffect, useRef, useState } from 'react'\nimport { createSnapSlider, TSnapSliderStateFull } from './snap-slider'\n\nexport interface TUseSnapSlider extends TSnapSliderStateFull {\n jumpTo: (index: number) => void\n goNext: () => void\n goPrev: () => void\n}\n\nexport function useSnapSlider(\n ref: MutableRefObject<HTMLDivElement | null>,\n count: number = 1,\n index: number = 0,\n circular = false,\n countHash?: string | number\n): TUseSnapSlider {\n const [, forceUpdate] = useState<number>(0)\n const mountedRef = useRef<boolean>()\n const [observer] = useState(() =>\n createSnapSlider({\n element: ref.current,\n count,\n index,\n circular,\n initalSubscriptionPublish: false,\n })\n )\n const result = observer.getState()\n useEffect(() => {\n if (mountedRef.current) {\n observer.jumpTo(0)\n observer.calculate()\n }\n }, [count, countHash, observer])\n useEffect(() => {\n mountedRef.current = true\n ref.current && observer.setElement(ref.current)\n const unsubscribe = observer.subscribe(() => {\n if (mountedRef.current) {\n forceUpdate((x) => x + 1)\n }\n })\n\n return () => {\n mountedRef.current = false\n unsubscribe()\n }\n }, [observer, forceUpdate])\n return {\n ...result,\n jumpTo: observer.jumpTo,\n goNext: observer.goNext,\n goPrev: observer.goPrev,\n }\n}\n"],"names":["useSnapSlider","ref","count","index","circular","countHash","forceUpdate","useState","mountedRef","useRef","observer","createSnapSlider","result","useEffect","unsubscribe","x"],"mappings":";;AASgB,SAAAA,EACdC,GACAC,IAAgB,GAChBC,IAAgB,GAChBC,IAAW,IACXC,GACgB;AAChB,QAAM,GAAGC,CAAW,IAAIC,EAAiB,CAAC,GACpCC,IAAaC,KACb,CAACC,CAAQ,IAAIH;AAAA,IAAS,MAC1BI,EAAiB;AAAA,MACf,SAASV,EAAI;AAAA,MACb,OAAAC;AAAA,MACA,OAAAC;AAAA,MACA,UAAAC;AAAA,MACA,2BAA2B;AAAA,IAAA,CAC5B;AAAA,EAAA,GAEGQ,IAASF,EAAS;AACxB,SAAAG,EAAU,MAAM;AACd,IAAIL,EAAW,YACbE,EAAS,OAAO,CAAC,GACjBA,EAAS,UAAU;AAAA,EAEpB,GAAA,CAACR,GAAOG,GAAWK,CAAQ,CAAC,GAC/BG,EAAU,MAAM;AACd,IAAAL,EAAW,UAAU,IACrBP,EAAI,WAAWS,EAAS,WAAWT,EAAI,OAAO;AACxC,UAAAa,IAAcJ,EAAS,UAAU,MAAM;AAC3C,MAAIF,EAAW,WACDF,EAAA,CAACS,MAAMA,IAAI,CAAC;AAAA,IAC1B,CACD;AAED,WAAO,MAAM;AACX,MAAAP,EAAW,UAAU,IACTM;IAAA;AAAA,EACd,GACC,CAACJ,GAAUJ,CAAW,CAAC,GACnB;AAAA,IACL,GAAGM;AAAA,IACH,QAAQF,EAAS;AAAA,IACjB,QAAQA,EAAS;AAAA,IACjB,QAAQA,EAAS;AAAA,EAAA;AAErB;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "use-snap-slider",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "React hook to manage css snap sliders",
5
5
  "type": "module",
6
6
  "main": "./dist/use-snap-slider.cjs.js",
@@ -16,22 +16,36 @@
16
16
  "homepage": "https://use-snap-slider.vercel.app",
17
17
  "scripts": {
18
18
  "dev": "vite",
19
- "build": "tsc && vite build",
19
+ "build": "tsc -p tsconfig.prod.json && vite build",
20
+ "build::source": "DISABLE_MINIFY=1 npm run build",
20
21
  "prepare": "npm run build",
21
- "build-vercel": "tsc && vite build --config vite.config.vercel.ts",
22
- "preview": "vite preview"
22
+ "build-vercel": "tsc -p tsconfig.prod.json && vite build --config vite.config.vercel.ts",
23
+ "preview": "vite preview",
24
+ "test": "npm run jest",
25
+ "jest": "NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest",
26
+ "coverage": "npm run jest -- --coverage=true"
27
+ },
28
+ "prettier": {
29
+ "semi": false,
30
+ "singleQuote": true
23
31
  },
24
32
  "devDependencies": {
33
+ "@testing-library/jest-dom": "^5.16.5",
34
+ "@testing-library/react": "^14.0.0",
35
+ "@types/jest": "^29.5.0",
25
36
  "@types/node": "^18.15.11",
26
37
  "@types/react": "^18.0.28",
27
38
  "@types/react-dom": "^18.0.11",
28
39
  "@vitejs/plugin-react": "^3.1.0",
29
40
  "autoprefixer": "^10.4.14",
30
41
  "classnames": "^2.3.2",
42
+ "jest": "^29.5.0",
43
+ "jest-environment-jsdom": "^29.5.0",
31
44
  "postcss": "^8.4.21",
32
45
  "react": "^18.2.0",
33
46
  "react-dom": "^18.2.0",
34
47
  "tailwindcss": "^3.2.7",
48
+ "ts-jest": "^29.1.0",
35
49
  "typescript": "^4.9.3",
36
50
  "vite": "^4.2.0",
37
51
  "vite-plugin-dts": "^2.2.0"