astro-swiper 2.2.2 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-swiper",
3
- "version": "2.2.2",
3
+ "version": "2.4.0",
4
4
  "description": "Astro component for swiper, dedicated to slider / carousel / photo swiper / slide, including thumbnails",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -35,9 +35,9 @@
35
35
  },
36
36
  "packageManager": "pnpm@10.30.3",
37
37
  "devDependencies": {
38
- "@biomejs/biome": "^2.4.4",
39
- "@types/node": "^24.11.0",
40
- "astro": "^5.18.0",
38
+ "@biomejs/biome": "^2.4.9",
39
+ "@types/node": "^24.12.0",
40
+ "astro": "^5.18.1",
41
41
  "prettier": "^3.8.1",
42
42
  "prettier-plugin-astro": "^0.14.1",
43
43
  "typescript": "^5.9.3"
@@ -58,6 +58,6 @@
58
58
  "thumbnail"
59
59
  ],
60
60
  "dependencies": {
61
- "swiper": "^12.1.2"
61
+ "swiper": "^12.1.3"
62
62
  }
63
63
  }
@@ -43,13 +43,13 @@ const {
43
43
 
44
44
  <script>
45
45
  import Swiper from 'swiper/bundle';
46
- import type { SwiperOptions } from 'swiper/types';
46
+ import type { AstroSwiperOptions } from 'astro-swiper';
47
47
 
48
48
  /** contains the swiper json object once created, for each uniqueClass */
49
49
  const _useSwiper: { [uniqueClass: string]: Swiper } = {};
50
50
 
51
51
  /** contains the option used when creating the swiper object for each uniqueClass */
52
- const _useOptions: { [uniqueClass: string]: SwiperOptions } = {};
52
+ const _useOptions: { [uniqueClass: string]: AstroSwiperOptions } = {};
53
53
 
54
54
  /** contains all the uniqueClass that have their swiper object delayed because the
55
55
  * related thumbnail swiper is not created yet
@@ -57,6 +57,97 @@ const {
57
57
  */
58
58
  const _useDelaySwiper: { [uniqueClass: string]: string } = {};
59
59
 
60
+ // Init swipers that have delayed initialization because the thumbnail swiper is not created yet
61
+ // If this is now the case, then it is intialized, as well as its observer if needed
62
+ function _initDelayedSwipers() {
63
+ Object.keys(_useDelaySwiper).forEach((delayedClass) => {
64
+ // swiper of uniqueClass "delayedClass" is delayed because it needs the swiper of uniqueClass
65
+ // "delayedThumbClass" to be created first
66
+ const delayedThumbClass = _useDelaySwiper[delayedClass];
67
+ if (_useSwiper[delayedThumbClass]) {
68
+ // the thumbnail swiper is created, we can create the swiper
69
+ delete _useDelaySwiper[delayedClass]; // remove it from the delayed list
70
+ const delayedOptions = _useOptions[delayedClass];
71
+ delayedOptions.thumbs = {
72
+ swiper: _useSwiper[delayedThumbClass], // add the thumbnail swiper link to the options
73
+ ...delayedOptions.thumbs,
74
+ };
75
+
76
+ _createSwiperAndObserver(
77
+ delayedClass,
78
+ delayedOptions,
79
+ document.querySelector(`.${delayedClass}`) as AstroSwiper,
80
+ );
81
+ _useOptions[delayedClass] = delayedOptions; // update the options with the thumbnail link
82
+ }
83
+ });
84
+ }
85
+
86
+ // initialize the swiper instance
87
+ // the autoplay may be stopped manually if it should be started by the observer
88
+ function _initSwiper(uniqueClass: string, options: AstroSwiperOptions, element: AstroSwiper) {
89
+ const swiper = new Swiper(`.${uniqueClass}`, options);
90
+ _useSwiper[uniqueClass] = swiper;
91
+ element.astroSwiper = swiper;
92
+
93
+ // stop the autoplay if it will be started by the observer
94
+ if (options.astro?.intersectionObserver?.controlAutoplay && options.autoplay) {
95
+ swiper.autoplay.stop();
96
+ }
97
+
98
+ _initDelayedSwipers();
99
+ return swiper;
100
+ }
101
+
102
+ function _createObserver(uniqueClass: string, options: AstroSwiperOptions, element: AstroSwiper) {
103
+ const observerOptions = options.astro?.intersectionObserver || {};
104
+ const observer = new IntersectionObserver((entries) => {
105
+ if (entries[0].isIntersecting) {
106
+ if (observerOptions?.initSwiper && !element.astroSwiper) {
107
+ _initSwiper(uniqueClass, options, element);
108
+ if (observerOptions?.disconnectOnInit) {
109
+ observer.disconnect();
110
+ }
111
+ }
112
+ }
113
+
114
+ const swiper = element?.astroSwiper;
115
+ if (!swiper) {
116
+ return;
117
+ }
118
+
119
+ if (observerOptions?.controlAutoplay && options.autoplay) {
120
+ if (entries[0].isIntersecting) {
121
+ swiper.autoplay.start();
122
+ } else {
123
+ swiper.autoplay.stop();
124
+ }
125
+ }
126
+ }, observerOptions.options);
127
+
128
+ observer.observe(element);
129
+ window.addEventListener('unload', observer.disconnect);
130
+ }
131
+
132
+ // create the swiper and the observer
133
+ // - init the swiper if it should not be done by the observer
134
+ // - create the observer if required
135
+ function _createSwiperAndObserver(
136
+ uniqueClass: string,
137
+ options: AstroSwiperOptions,
138
+ element: AstroSwiper,
139
+ ) {
140
+ if (!options.astro?.intersectionObserver?.initSwiper) {
141
+ // create the swiper immediatly
142
+ _initSwiper(uniqueClass, options, element);
143
+ }
144
+
145
+ // create the observer. It may init the swiper
146
+ if (options.astro?.intersectionObserver) {
147
+ _createObserver(uniqueClass, options, element);
148
+ }
149
+ }
150
+
60
151
  class AstroSwiper extends HTMLElement {
61
152
  /** pointer to the swiper structure that was created using "new",
62
153
  * even when not initialized */
@@ -67,50 +158,26 @@ const {
67
158
  this.astroSwiper = undefined;
68
159
 
69
160
  // Read the message from the data attribute.
70
- const options = JSON.parse(this.dataset.options || '{}');
161
+ const options: AstroSwiperOptions = JSON.parse(this.dataset.options || '{}');
71
162
  // to have more than 1 swiper in a single page
72
163
  const uniqueClass = this.dataset.uniqueclass || '';
73
164
  const linkToThumbUniqueClass = this.dataset.linktothumbuniqueclass || '';
74
165
 
75
- if (linkToThumbUniqueClass === '') {
76
- // no thumbnail link - the swiper can be created immediatly
77
- const swiper = new Swiper(`.${uniqueClass}`, options);
78
- _useSwiper[uniqueClass] = swiper;
79
- this.astroSwiper = swiper;
80
- } else {
81
- // a thumbnail link is provided
82
- // if the thumbnail swiper is already created, the main slider can be created also
83
- // otherwise, it will be added in the delayed swiper list
84
- if (_useSwiper[linkToThumbUniqueClass] !== undefined) {
166
+ // no thumbnail link, or link to thumbnail swiper already created,
167
+ // the swiper can be created or not immediatly depending on the observer option
168
+ if (!linkToThumbUniqueClass || _useSwiper[linkToThumbUniqueClass]) {
169
+ if (linkToThumbUniqueClass) {
85
170
  options.thumbs = { swiper: _useSwiper[linkToThumbUniqueClass], ...options.thumbs };
86
- const swiper = new Swiper(`.${uniqueClass}`, options);
87
- _useSwiper[uniqueClass] = swiper;
88
- this.astroSwiper = swiper;
89
- } else {
90
- // cannot create the swiper as the thumbnail swiper not created yet
91
- // will be done later
92
- _useDelaySwiper[uniqueClass] = linkToThumbUniqueClass;
93
171
  }
172
+ // create the swiper and the observer if needed
173
+ _createSwiperAndObserver(uniqueClass, options, this);
174
+ } else {
175
+ // cannot create the swiper as the thumbnail swiper not created yet
176
+ // is delayed until the thumbnail swiper is initialized.
177
+ _useDelaySwiper[uniqueClass] = linkToThumbUniqueClass;
94
178
  }
95
179
 
96
180
  _useOptions[uniqueClass] = options;
97
-
98
- // look if any delayed swiper can be created, that is its related thumbnail swiper is now created
99
- Object.keys(_useDelaySwiper).forEach((delayedClass) => {
100
- const delayedThumbClass = _useDelaySwiper[delayedClass];
101
- if (_useSwiper[delayedThumbClass] !== undefined) {
102
- const delayedOptions = _useOptions[delayedClass];
103
- delayedOptions.thumbs = {
104
- swiper: _useSwiper[delayedThumbClass],
105
- ...delayedOptions.thumbs,
106
- };
107
- const swiper = new Swiper(`.${delayedClass}`, delayedOptions);
108
- _useSwiper[delayedClass] = swiper;
109
- (document.querySelector(`.${delayedClass}`) as AstroSwiper).astroSwiper = swiper;
110
- _useOptions[delayedClass] = delayedOptions;
111
- delete _useDelaySwiper[delayedClass];
112
- }
113
- });
114
181
  }
115
182
  }
116
183
 
@@ -0,0 +1,19 @@
1
+ ---
2
+ // Copyright (c) Pascal Brand
3
+ // MIT License
4
+
5
+ import 'swiper/css/bundle';
6
+
7
+ import type { HTMLAttributes } from 'astro/types';
8
+
9
+ interface Props extends HTMLAttributes<'div'> {
10
+ /** add the default swiper class, true by default */
11
+ addDefaultClass?: boolean;
12
+ }
13
+
14
+ const { class: className = null, addDefaultClass = true, ...props } = Astro.props;
15
+ ---
16
+
17
+ <div class:list={[addDefaultClass ? 'swiper-lazy-preloader' : null, className]} {...props}>
18
+ <slot />
19
+ </div>
package/src/index.ts CHANGED
@@ -4,6 +4,32 @@
4
4
  import type { Swiper, SwiperOptions } from 'swiper/types';
5
5
  import type { HTMLAttributes } from 'astro/types';
6
6
 
7
+ /** Swiper options for the Astro component.
8
+ * Basically the same as the original SwiperOptions, but extended
9
+ * with new capabilities
10
+ */
11
+ export interface AstroSwiperOptions extends SwiperOptions {
12
+ /** options specific to astro-swiper component */
13
+ astro?: {
14
+ /** intersection observer options: an observer can be added to control the swiper when it appears / disappears in the screen.
15
+ * The observer is created using IntersectionObserver
16
+ * The behavior of the observer is controlled by the following properties
17
+ * When observer is not provided, no observer is created.
18
+ */
19
+ intersectionObserver?: {
20
+ /** true to initialize the swiper when the element appears in the screen */
21
+ initSwiper?: boolean;
22
+ /** true to disconnect the observer once the swiper is initialized */
23
+ disconnectOnInit?: boolean;
24
+ /** true to start and stop the autoplay when the swiper appears and disappears from the screen, respectively. */
25
+ controlAutoplay?: boolean;
26
+ /** options for the IntersectionObserver */
27
+ options?: IntersectionObserverInit;
28
+ };
29
+ /** TODO: uniqueClass and linkToThumbUniqueClass may be part of it */
30
+ };
31
+ }
32
+
7
33
  /** properties passed to the <Swiper> component
8
34
  * It extends a div (that is may have class, style,...), plus other attributes
9
35
  * Note that all other components (<SwiperSlide>, <SwiperButtonNext>...) extends a div only
@@ -12,7 +38,7 @@ export interface AstroSwiperType extends HTMLAttributes<'div'> {
12
38
  /** swiper options, to set autoplay, navigation, thumbnails,...
13
39
  * check fullset of options: https://swiperjs.com/swiper-api#parameters
14
40
  */
15
- options?: SwiperOptions;
41
+ options?: AstroSwiperOptions;
16
42
 
17
43
  /** unique class to be able to retrieve the swiper instance, if required
18
44
  * Mandatory on thumbnail for example
@@ -43,6 +69,7 @@ export interface AstroSwiperType extends HTMLAttributes<'div'> {
43
69
  export { default as Swiper } from './components/Swiper.astro';
44
70
  export { default as SwiperButtonNext } from './components/SwiperButtonNext.astro';
45
71
  export { default as SwiperButtonPrev } from './components/SwiperButtonPrev.astro';
72
+ export { default as SwiperLazyPreloader } from './components/SwiperLazyPreloader.astro';
46
73
  export { default as SwiperPagination } from './components/SwiperPagination.astro';
47
74
  export { default as SwiperScrollbar } from './components/SwiperScrollbar.astro';
48
75
  export { default as SwiperSlide } from './components/SwiperSlide.astro';