use-snap-slider 0.0.2 → 0.0.4

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,200 @@
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 state = useSnapSlider(ref, slides.count)
36
+ const pages = Array.from(Array(state.count).keys())
37
+ return (
38
+ <div>
39
+ <div className="flex scroll-smooth snap-x snap-mandatory overflow-x-auto w-full" 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={() => state.jumpTo(page)} disabled={page === state.index}>{page + 1}</button>
49
+ ))}
50
+ </nav>
51
+ <nav aria-label="Prev / Next navigation">
52
+ <button onClick={state.goPrev} disabled={!state.prevEnabled}>Prev</button>
53
+ <button onClick={state.goNext} disabled={!state.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
+ } = createSnapSlider({
136
+ element: HTMLDivElement | null,
137
+ count?:number = 1,
138
+ countDelta?:number,
139
+ index?:number = 0,
140
+ circular?:boolean,
141
+ indexDelta?:number,
142
+ itemSelector?:string = ':scope > *',
143
+ })
144
+ ```
145
+
146
+ ## Adding nessesary styles
147
+
148
+ 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:
149
+
150
+ * [React component](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/react-example/SnapSliderReact.tsx)
151
+ * [Vanilla JS function](https://github.com/gerhardsletten/use-snap-slider/blob/main/src/vanilla-example/create-snap-slider.ts)
152
+
153
+ ### TailwindCSS
154
+
155
+ See also tailwinds own documentation for [scroll snap](https://tailwindcss.com/docs/scroll-snap-type)
156
+
157
+ ```html
158
+ <div class="flex scroll-smooth snap-x snap-mandatory overflow-x-auto">
159
+ <div class="flex snap-start shrink-0">
160
+ Slide 1
161
+ </div>
162
+ <div class="flex snap-start shrink-0">
163
+ Slide 2
164
+ </div>
165
+ </div>
166
+ ```
167
+
168
+ ### Basic css
169
+
170
+ ```html
171
+ <style>
172
+ .css-slider {
173
+ display: flex;
174
+ overflow-x: auto;
175
+ scroll-snap-type: x mandatory;
176
+ scroll-behavior: smooth;
177
+ -webkit-overflow-scrolling: touch;
178
+ }
179
+ .css-slider::-webkit-scrollbar {
180
+ @apply hidden;
181
+ }
182
+ .css-slider-item {
183
+ display: flex;
184
+ scroll-snap-align: start;
185
+ flex-shrink: 0;
186
+ }
187
+ .css-slider-item-half {
188
+ width: 50%;
189
+ }
190
+ </style>
191
+ <!-- Markup -->
192
+ <div class="css-slider">
193
+ <div class="css-slider-item css-slider-item-half">
194
+ Slide 1
195
+ </div>
196
+ <div class="css-slider-item css-slider-item-half">
197
+ Slide 2
198
+ </div>
199
+ </div>
200
+ ```
@@ -20,13 +20,12 @@ export type TSnapListner = (params: TSnapSliderStateFull) => void;
20
20
  export interface TSnapSliderParams extends TSnapSliderStateUpdate {
21
21
  element: HTMLElement | null;
22
22
  itemSelector?: string;
23
- initalSubscriptionPublish?: boolean;
24
23
  circular?: boolean;
25
24
  }
26
25
  export type TSnapSliderJumpToFn = (index?: number, indexDelta?: number) => void;
27
26
  export interface TSnapSlider {
28
27
  destroy: () => void;
29
- getState: (count?: number, index?: number) => TSnapSliderStateFull;
28
+ getState: () => TSnapSliderStateFull;
30
29
  jumpTo: TSnapSliderJumpToFn;
31
30
  goNext: () => void;
32
31
  goPrev: () => void;
@@ -34,5 +33,5 @@ export interface TSnapSlider {
34
33
  setElement: (el: HTMLElement) => void;
35
34
  calculate: () => void;
36
35
  }
37
- export declare function createSnapSlider({ element: _element, count, countDelta, index, circular, indexDelta, initalSubscriptionPublish, itemSelector, }: TSnapSliderParams): TSnapSlider;
36
+ export declare function createSnapSlider({ element: _element, count, countDelta, index, circular, indexDelta, itemSelector, }: TSnapSliderParams): TSnapSlider;
38
37
  export {};
@@ -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,c;return function(){const v=this,p=arguments;h?(clearTimeout(r),r=setTimeout(()=>{Date.now()-c>=u&&(f.apply(v,p),c=Date.now())},Math.max(u-(Date.now()-c),0))):(f.apply(v,p),c=Date.now(),h=!0)}};function B({element:f,count:u=1,countDelta:h,index:r=0,circular:c,indexDelta:v,itemSelector:p=":scope > *"}){let T=r,a={index:r,indexDelta:v||r,count:u,countDelta:h||u},S=r,i=1,D=[],g=!1,x=0,o;function W(){if(o){const t=o.scrollLeft,{indexDelta:e}=a;if(x=e*(o.offsetWidth/i),S!==e){const n=Math.abs(t-x),l=o.offsetWidth*2;S=e,g=!0,o.scroll({left:x,top:0,behavior:n>l?"smooth":void 0})}else T&&(g=!0,o.scroll({left:x,top:0}),T=void 0)}}let P=!1,d=[];const A=t=>(d.push(t),P&&t(b()),()=>{d=d.filter(e=>e!==t),d.length<1&&I()});function O(){d.forEach(t=>{t(b())})}const b=()=>{const{indexDelta:t,countDelta:e}=a;return{...a,prevEnabled:c||t>0,nextEnabled:c||e-i>t}};function m(t){let e=!1,n=!1;Object.keys(t).forEach(s=>{a[s]!==t[s]&&(a[s]=Number(t[s]),e=!0,s==="indexDelta"&&(n=!0))}),e&&(P=d.length===0,O(),n&&W())}function y(t){const{index:e,indexDelta:n}=t,{countDelta:l,count:s}=a,L=l-i;return{index:n<L?e:s-1,indexDelta:n}}function M(){if(o){let t=0,e=0;D=[],o.querySelectorAll(p).forEach(N=>{D.push(t),t+=N.clientWidth,e=N.clientWidth}),i=Math.round(o.offsetWidth/e);const n=D.length,l=Math.ceil(n/i),{index:s}=a,L=s+1>l?{index:0,indexDelta:0}:{};m({count:l,countDelta:n,...L})}}let E=!1;function R(){if(!E&&o){const t=o.scrollLeft;window.requestAnimationFrame(()=>{if(g)Math.abs(x-t)<1&&(g=!1);else{const e=D.reduce((l,s)=>Math.abs(s-t)<Math.abs(l-t)?s:l),n=D.findIndex(l=>l===e);S=n,m(y({index:Math.floor(n/i),indexDelta:n}))}E=!1}),E=!0}}const F=q(R,200),j=q(M,500);function z(t){o&&I(),o=t,W(),M(),o==null||o.addEventListener("scroll",F),window.addEventListener("resize",j)}f&&z(f);const w=function(t,e){e!==void 0&&m(y({index:Math.floor(e/i),indexDelta:e})),t!==void 0&&m(y({index:t,indexDelta:t*i}))},I=()=>{o==null||o.removeEventListener("scroll",F),window.removeEventListener("resize",j)};return{destroy:I,getState:b,subscribe:A,jumpTo:w,setElement:z,calculate:M,goNext:()=>{const{countDelta:t,indexDelta:e}=a,n=t-i,l=e+i<=n?e+i:c&&e===n?0:n;w(void 0,l)},goPrev:()=>{const{indexDelta:t,countDelta:e}=a,n=e-i,l=t-i>=0?t-i:c&&t===0?n:0;w(void 0,l)}}}exports.createSnapSlider=B;
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 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 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 element.scroll({\n left,\n top: 0,\n behavior: distance > limitInstantScroll ? 'smooth' : undefined,\n })\n } else {\n if (initalIndex) {\n muteScrollListner = true\n element.scroll({\n left,\n top: 0,\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 (publishDirty) {\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 < 1) {\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","itemSelector","initalIndex","state","prevIndexDelta","slidesPerPage","itemPositions","muteScrollListner","left","element","updateIndexDelta","prev","distance","limitInstantScroll","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,151 @@
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 G({
11
+ element: f,
12
+ count: u = 1,
13
+ countDelta: h,
14
+ index: r = 0,
15
+ circular: c,
16
+ indexDelta: v,
17
+ itemSelector: p = ":scope > *"
29
18
  }) {
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
19
+ let T = r, a = {
20
+ index: r,
21
+ indexDelta: v || r,
22
+ count: u,
23
+ countDelta: h || u
24
+ }, b = r, i = 1, x = [], m = !1, D = 0, o;
25
+ function W() {
26
+ if (o) {
27
+ const t = o.scrollLeft, { indexDelta: e } = a;
28
+ if (D = e * (o.offsetWidth / i), b !== e) {
29
+ const n = Math.abs(t - D), l = o.offsetWidth * 2;
30
+ b = e, m = !0, o.scroll({
31
+ left: D,
32
+ top: 0,
33
+ behavior: n > l ? "smooth" : void 0
66
34
  });
67
- initalIndex = void 0;
68
- }
35
+ } else
36
+ T && (m = !0, o.scroll({
37
+ left: D,
38
+ top: 0
39
+ }), T = void 0);
69
40
  }
70
41
  }
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());
42
+ let P = !1, d = [];
43
+ const A = (t) => (d.push(t), P && t(E()), () => {
44
+ d = d.filter((e) => e !== t), d.length < 1 && I();
45
+ });
46
+ function O() {
47
+ d.forEach((t) => {
48
+ t(E());
84
49
  });
85
50
  }
86
- const getState = () => {
87
- const { indexDelta: indexDelta2, countDelta: countDelta2 } = state;
51
+ const E = () => {
52
+ const { indexDelta: t, countDelta: e } = a;
88
53
  return {
89
- ...state,
90
- prevEnabled: circular || indexDelta2 > 0,
91
- nextEnabled: circular || countDelta2 - slidesPerPage > indexDelta2
54
+ ...a,
55
+ prevEnabled: c || t > 0,
56
+ nextEnabled: c || e - i > t
92
57
  };
93
58
  };
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
- }
59
+ function g(t) {
60
+ let e = !1, n = !1;
61
+ Object.keys(
62
+ t
63
+ ).forEach((s) => {
64
+ a[s] !== t[s] && (a[s] = Number(t[s]), e = !0, s === "indexDelta" && (n = !0));
65
+ }), e && (P = d.length === 0, O(), n && W());
117
66
  }
118
- function fixIndex(nextIndex) {
119
- const { index: index2, indexDelta: indexDelta2 } = nextIndex;
120
- const { countDelta: countDelta2, count: count2 } = state;
121
- const last = countDelta2 - slidesPerPage;
67
+ function M(t) {
68
+ const { index: e, indexDelta: n } = t, { countDelta: l, count: s } = a, L = l - i;
122
69
  return {
123
- index: indexDelta2 < last ? index2 : count2 - 1,
124
- indexDelta: indexDelta2
70
+ index: n < L ? e : s - 1,
71
+ indexDelta: n
125
72
  };
126
73
  }
127
- function calculate() {
128
- if (!element) {
129
- return;
74
+ function S() {
75
+ if (o) {
76
+ let t = 0, e = 0;
77
+ x = [], o.querySelectorAll(p).forEach((j) => {
78
+ x.push(t), t += j.clientWidth, e = j.clientWidth;
79
+ }), i = Math.round(o.offsetWidth / e);
80
+ const n = x.length, l = Math.ceil(n / i), { index: s } = a, L = s + 1 > l ? {
81
+ index: 0,
82
+ indexDelta: 0
83
+ } : {};
84
+ g({
85
+ count: l,
86
+ countDelta: n,
87
+ ...L
88
+ });
130
89
  }
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
90
  }
153
- let ticking = false;
154
- function onScroll() {
155
- if (!ticking && element) {
156
- const scrollLeft = element.scrollLeft;
91
+ let w = !1;
92
+ function R() {
93
+ if (!w && o) {
94
+ const t = o.scrollLeft;
157
95
  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
96
+ if (m)
97
+ Math.abs(D - t) < 1 && (m = !1);
98
+ else {
99
+ const e = x.reduce((l, s) => Math.abs(s - t) < Math.abs(l - t) ? s : l), n = x.findIndex((l) => l === e);
100
+ b = n, g(
101
+ M({
102
+ index: Math.floor(n / i),
103
+ indexDelta: n
173
104
  })
174
105
  );
175
106
  }
176
- ticking = false;
177
- });
178
- ticking = true;
107
+ w = !1;
108
+ }), w = !0;
179
109
  }
180
110
  }
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);
111
+ const F = q(R, 200), z = q(S, 500);
112
+ function N(t) {
113
+ o && I(), o = t, W(), S(), o == null || o.addEventListener("scroll", F), window.addEventListener("resize", z);
192
114
  }
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);
115
+ f && N(f);
116
+ const y = function(t, e) {
117
+ e !== void 0 && g(
118
+ M({
119
+ index: Math.floor(e / i),
120
+ indexDelta: e
121
+ })
122
+ ), t !== void 0 && g(
123
+ M({
124
+ index: t,
125
+ indexDelta: t * i
126
+ })
127
+ );
128
+ }, I = () => {
129
+ o == null || o.removeEventListener("scroll", F), window.removeEventListener("resize", z);
227
130
  };
228
131
  return {
229
- destroy,
230
- getState,
231
- subscribe,
232
- jumpTo,
233
- setElement,
234
- calculate,
235
- goNext,
236
- goPrev
132
+ destroy: I,
133
+ getState: E,
134
+ subscribe: A,
135
+ jumpTo: y,
136
+ setElement: N,
137
+ calculate: S,
138
+ goNext: () => {
139
+ const { countDelta: t, indexDelta: e } = a, n = t - i, l = e + i <= n ? e + i : c && e === n ? 0 : n;
140
+ y(void 0, l);
141
+ },
142
+ goPrev: () => {
143
+ const { indexDelta: t, countDelta: e } = a, n = e - i, l = t - i >= 0 ? t - i : c && t === 0 ? n : 0;
144
+ y(void 0, l);
145
+ }
237
146
  };
238
147
  }
239
148
  export {
240
- createSnapSlider
149
+ G as createSnapSlider
241
150
  };
151
+ //# 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 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 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 element.scroll({\n left,\n top: 0,\n behavior: distance > limitInstantScroll ? 'smooth' : undefined,\n })\n } else {\n if (initalIndex) {\n muteScrollListner = true\n element.scroll({\n left,\n top: 0,\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 (publishDirty) {\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 < 1) {\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","itemSelector","initalIndex","state","prevIndexDelta","slidesPerPage","itemPositions","muteScrollListner","left","element","updateIndexDelta","prev","distance","limitInstantScroll","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,a){const[,s]=t.useState(0),r=t.useRef(),[e]=t.useState(()=>f.createSnapSlider({element:u.current,count:n,index:c,circular:o})),i=e.getState();return t.useEffect(()=>{r.current&&(e.jumpTo(0),e.calculate())},[n,a,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]),{...i,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 })\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,CAAA,CACD,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,32 @@
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 c } from "react";
2
+ import { createSnapSlider as S } from "./snap-slider.es.js";
3
+ function d(r, u = 1, s = 0, a = !1, f) {
4
+ const [, n] = o(0), t = p(), [e] = o(
5
+ () => S({
6
+ element: r.current,
7
+ count: u,
8
+ index: s,
9
+ circular: a
13
10
  })
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
- }
11
+ ), m = e.getState();
12
+ return c(() => {
13
+ t.current && (e.jumpTo(0), e.calculate());
14
+ }, [u, f, e]), c(() => {
15
+ t.current = !0, r.current && e.setElement(r.current);
16
+ const i = e.subscribe(() => {
17
+ t.current && n((l) => l + 1);
29
18
  });
30
- ref.current && observer.setElement(ref.current);
31
19
  return () => {
32
- mountedRef.current = false;
33
- unsubscribe();
20
+ t.current = !1, i();
34
21
  };
35
- }, [observer, forceUpdate]);
36
- return {
37
- ...result,
38
- jumpTo: observer.jumpTo,
39
- goNext: observer.goNext,
40
- goPrev: observer.goPrev
22
+ }, [e, n]), {
23
+ ...m,
24
+ jumpTo: e.jumpTo,
25
+ goNext: e.goNext,
26
+ goPrev: e.goPrev
41
27
  };
42
28
  }
43
29
  export {
44
- useSnapSlider
30
+ d as useSnapSlider
45
31
  };
32
+ //# 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 })\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,IAAA,CACD;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.2",
3
+ "version": "0.0.4",
4
4
  "description": "React hook to manage css snap sliders",
5
5
  "type": "module",
6
6
  "main": "./dist/use-snap-slider.cjs.js",
@@ -13,24 +13,39 @@
13
13
  "type": "git",
14
14
  "url": "git+https://github.com/gerhardsletten/use-snap-slider.git"
15
15
  },
16
+ "homepage": "https://use-snap-slider.vercel.app",
16
17
  "scripts": {
17
18
  "dev": "vite",
18
- "build": "tsc && vite build",
19
+ "build": "tsc -p tsconfig.prod.json && vite build",
20
+ "build::source": "DISABLE_MINIFY=1 npm run build",
19
21
  "prepare": "npm run build",
20
- "build-vercel": "tsc && vite build --config vite.config.vercel.ts",
21
- "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
22
31
  },
23
32
  "devDependencies": {
33
+ "@testing-library/jest-dom": "^5.16.5",
34
+ "@testing-library/react": "^14.0.0",
35
+ "@types/jest": "^29.5.0",
24
36
  "@types/node": "^18.15.11",
25
37
  "@types/react": "^18.0.28",
26
38
  "@types/react-dom": "^18.0.11",
27
39
  "@vitejs/plugin-react": "^3.1.0",
28
40
  "autoprefixer": "^10.4.14",
29
41
  "classnames": "^2.3.2",
42
+ "jest": "^29.5.0",
43
+ "jest-environment-jsdom": "^29.5.0",
30
44
  "postcss": "^8.4.21",
31
45
  "react": "^18.2.0",
32
46
  "react-dom": "^18.2.0",
33
47
  "tailwindcss": "^3.2.7",
48
+ "ts-jest": "^29.1.0",
34
49
  "typescript": "^4.9.3",
35
50
  "vite": "^4.2.0",
36
51
  "vite-plugin-dts": "^2.2.0"