astro-swiper 2.4.0 → 2.5.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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center" style="background-color: dark-grey; padding: 1rem;">
2
2
  <a href="https://swiperjs.com" target="_blank"><img width="70" width="auto" src="images/swiper-logo.svg"></a>
3
3
  <a href="https://astro.build/" target="_blank"><img height="68" width="auto" src="images/astro-logo.svg"></a>
4
-
4
+
5
5
  # Astro Swiper
6
6
 
7
7
  > Astro Swiper - native component for [Swiper](https://github.com/nolimits4web/swiper).
@@ -74,7 +74,7 @@ You can also look at how others are using `astro-swiper` in public github repo:
74
74
  - the famous astro template [astroplate](https://github.com/zeon-studio/astroplate) in the
75
75
  [testominial section](https://zeon.studio/preview?project=astroplate)
76
76
  (cf. **_What Users Are Saying About Astroplate_**):
77
- autoplay, pagination and breakpoints are used
77
+ autoplay, pagination and breakpoints are used.
78
78
  - the popular astro template [pinwheel-astro](https://github.com/themefisher/pinwheel-astro)
79
79
  is using `astro-swiper` in several places:
80
80
  [testimonial section](https://pinwheel-astro.vercel.app/),
@@ -91,14 +91,18 @@ You can also look at how others are using `astro-swiper` in public github repo:
91
91
  [main page](https://tf-bigspring-light-astro.vercel.app/) with customized pagination.
92
92
  - [Women Techmakers organized by GDG Madrid](https://github.com/wtmgdgmadrid/wtmgdgmadrid.github.io)
93
93
  is using pagination and autoplay at different places in their
94
- [page](http://wtmgdgmadrid.github.io/)
94
+ [page](http://wtmgdgmadrid.github.io/).
95
95
  - [kando-menu](https://github.com/make-42/kando-menu.github.io) is using `astro-swiper`
96
- with pagination, card effect, and coverflow effect as displayed in [kando.menu](https://kando.menu/)
97
- - [astroimagej](https://github.com/AstroImageJ/astroimagej) is using pagination with progress bar
96
+ with pagination, card effect, and coverflow effect as displayed in [kando.menu](https://kando.menu/).
97
+ - [astroimagej](https://github.com/AstroImageJ/astroimagej) is using pagination with progress bar.
98
+ - [rustdesk.com](https://github.com/rustdesk/doc.rustdesk.com) makes use of `<SwiperLazyPreloader/>`
99
+ to add a preloader element.
98
100
  - ... and many others such as
99
101
  [Cinerama](https://github.com/RaiderMr3003/Cinerama) and
100
102
  [pfm-landing-page](https://github.com/RichardAgain/pfm-landing-page)
101
- using `astro-swiper` in the hero section
103
+ using `astro-swiper` in the hero section,
104
+ [folex-lite-astro](https://github.com/getastrothemes/folex-lite-astro)
105
+ using it in the portfolio page,...
102
106
 
103
107
  ## Help needed?
104
108
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-swiper",
3
- "version": "2.4.0",
3
+ "version": "2.5.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",
@@ -18,7 +18,7 @@
18
18
  "bugs": {
19
19
  "url": "https://github.com/pascal-brand38/astro-swiper/issues"
20
20
  },
21
- "homepage": "https://github.com/pascal-brand38/astro-swiper",
21
+ "homepage": "https://pascal-brand38.github.io/astro-dev/packages/astro-swiper/",
22
22
  "exports": {
23
23
  ".": {
24
24
  "types": "./index.ts",
@@ -9,20 +9,40 @@ type Props = AstroSwiperType;
9
9
 
10
10
  const {
11
11
  options = {},
12
- uniqueClass = `astro-swiper-${Math.random().toString(36).slice(2, 11)}`,
12
+ uniqueClass: removedUniqueClass, // remove it once deprecated uniqueClass prop is removed
13
13
  class: className = null,
14
- linkToThumbUniqueClass = null,
14
+ linkToThumbUniqueClass: removedLinkToThumbUniqueClass, // remove it once deprecated uniqueClass prop is removed
15
15
  addDefaultClass = true,
16
- useCustomElement = true,
17
16
  ...props
18
17
  } = Astro.props;
18
+
19
+ // check for deprecated useCustomElement prop and set the options.astro.useCustomElement
20
+ // option accordingly if not set, to keep legacy
21
+ if (options?.astro?.useCustomElement === undefined && Astro.props.useCustomElement === false) {
22
+ if (!options.astro) {
23
+ options.astro = {};
24
+ }
25
+ options.astro.useCustomElement = false;
26
+ }
27
+
28
+ // once Astro.props.uniqueClass is removed, uniqueClass can be directly set to the generated unique class name
29
+ const uniqueClass =
30
+ Astro.props.uniqueClass || `astro-swiper-${Math.random().toString(36).slice(2, 11)}`;
31
+
32
+ // check for deprecated useCustomElement prop and set the options.astro.useCustomElement
33
+ // option accordingly if not set, to keep legacy
34
+ if (options?.astro?.thumbSwiperUniqueSelector === undefined && Astro.props.linkToThumbUniqueClass) {
35
+ if (!options.astro) {
36
+ options.astro = {};
37
+ }
38
+ options.astro.thumbSwiperUniqueSelector = `.${Astro.props.linkToThumbUniqueClass}`;
39
+ }
19
40
  ---
20
41
 
21
42
  <!-- Slider main container -->{
22
- useCustomElement ? (
43
+ options?.astro?.useCustomElement !== false ? (
23
44
  <astro-swiper
24
45
  data-options={JSON.stringify(options)}
25
- data-linktothumbuniqueclass={linkToThumbUniqueClass}
26
46
  data-uniqueclass={uniqueClass}
27
47
  class:list={[addDefaultClass ? 'swiper' : null, uniqueClass, className]}
28
48
  {...props}
@@ -31,11 +51,7 @@ const {
31
51
  </astro-swiper>
32
52
  ) : (
33
53
  <div class:list={[addDefaultClass ? 'swiper' : null, uniqueClass, className]} {...props}>
34
- <astro-swiper
35
- data-options={JSON.stringify(options)}
36
- data-linktothumbuniqueclass={linkToThumbUniqueClass}
37
- data-uniqueclass={uniqueClass}
38
- />
54
+ <astro-swiper data-options={JSON.stringify(options)} data-uniqueclass={uniqueClass} />
39
55
  <slot />
40
56
  </div>
41
57
  )
@@ -43,51 +59,62 @@ const {
43
59
 
44
60
  <script>
45
61
  import Swiper from 'swiper/bundle';
46
- import type { AstroSwiperOptions } from 'astro-swiper';
62
+ import { getSwiperFromUniqueSelector } from '../index';
63
+ import type { AstroSwiperOptions, selectorStringType } from '../index';
47
64
 
48
- /** contains the swiper json object once created, for each uniqueClass */
49
- const _useSwiper: { [uniqueClass: string]: Swiper } = {};
65
+ const getSwiperFromUniqueSelectorOptions = {
66
+ // to avoid warning when the swiper is not initialized yet, but will be in the future
67
+ // (for example when using thumbnails, the main swiper is created before the thumbnail
68
+ // swiper, so it is normal that it is not found at this moment)
69
+ mayBeUndefined: true,
70
+ };
50
71
 
51
- /** contains the option used when creating the swiper object for each uniqueClass */
52
- const _useOptions: { [uniqueClass: string]: AstroSwiperOptions } = {};
72
+ /** contains the option used when creating the swiper object for each uniqueSelector */
73
+ const _useOptions: { [uniqueSelector: string]: AstroSwiperOptions } = {};
53
74
 
54
- /** contains all the uniqueClass that have their swiper object delayed because the
75
+ /** contains all the uniqueSelector that have their swiper object delayed because the
55
76
  * related thumbnail swiper is not created yet
56
- * For each uniqueClass, is equal to the thumbnail slider uniqueClass
77
+ * For each uniqueSelector, is equal to the thumbnail slider uniqueSelector
57
78
  */
58
- const _useDelaySwiper: { [uniqueClass: string]: string } = {};
79
+ const _useDelaySwiper: { [uniqueSelector: string]: string } = {};
59
80
 
60
81
  // Init swipers that have delayed initialization because the thumbnail swiper is not created yet
61
82
  // If this is now the case, then it is intialized, as well as its observer if needed
62
83
  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]) {
84
+ Object.keys(_useDelaySwiper).forEach((delayedSelector) => {
85
+ // swiper of uniqueSelector "delayedSelector" is delayed because it needs the swiper of uniqueSelector
86
+ // "delayedThumbSelector" to be created first
87
+ const delayedThumbSelector = _useDelaySwiper[delayedSelector];
88
+ const swiper = getSwiperFromUniqueSelector(
89
+ delayedThumbSelector,
90
+ getSwiperFromUniqueSelectorOptions,
91
+ );
92
+ if (swiper) {
68
93
  // 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];
94
+ delete _useDelaySwiper[delayedSelector]; // remove it from the delayed list
95
+ const delayedOptions = _useOptions[delayedSelector];
71
96
  delayedOptions.thumbs = {
72
- swiper: _useSwiper[delayedThumbClass], // add the thumbnail swiper link to the options
97
+ swiper: swiper, // add the thumbnail swiper link to the options
73
98
  ...delayedOptions.thumbs,
74
99
  };
75
100
 
76
101
  _createSwiperAndObserver(
77
- delayedClass,
102
+ delayedSelector,
78
103
  delayedOptions,
79
- document.querySelector(`.${delayedClass}`) as AstroSwiper,
104
+ document.querySelector(delayedSelector) as AstroSwiper,
80
105
  );
81
- _useOptions[delayedClass] = delayedOptions; // update the options with the thumbnail link
82
106
  }
83
107
  });
84
108
  }
85
109
 
86
110
  // initialize the swiper instance
87
111
  // 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;
112
+ function _initSwiper(
113
+ uniqueSelector: selectorStringType,
114
+ options: AstroSwiperOptions,
115
+ element: AstroSwiper,
116
+ ) {
117
+ const swiper = new Swiper(uniqueSelector, options);
91
118
  element.astroSwiper = swiper;
92
119
 
93
120
  // stop the autoplay if it will be started by the observer
@@ -99,12 +126,16 @@ const {
99
126
  return swiper;
100
127
  }
101
128
 
102
- function _createObserver(uniqueClass: string, options: AstroSwiperOptions, element: AstroSwiper) {
129
+ function _createObserver(
130
+ uniqueSelector: selectorStringType,
131
+ options: AstroSwiperOptions,
132
+ element: AstroSwiper,
133
+ ) {
103
134
  const observerOptions = options.astro?.intersectionObserver || {};
104
135
  const observer = new IntersectionObserver((entries) => {
105
136
  if (entries[0].isIntersecting) {
106
137
  if (observerOptions?.initSwiper && !element.astroSwiper) {
107
- _initSwiper(uniqueClass, options, element);
138
+ _initSwiper(uniqueSelector, options, element);
108
139
  if (observerOptions?.disconnectOnInit) {
109
140
  observer.disconnect();
110
141
  }
@@ -133,18 +164,18 @@ const {
133
164
  // - init the swiper if it should not be done by the observer
134
165
  // - create the observer if required
135
166
  function _createSwiperAndObserver(
136
- uniqueClass: string,
167
+ uniqueSelector: selectorStringType,
137
168
  options: AstroSwiperOptions,
138
169
  element: AstroSwiper,
139
170
  ) {
140
171
  if (!options.astro?.intersectionObserver?.initSwiper) {
141
172
  // create the swiper immediatly
142
- _initSwiper(uniqueClass, options, element);
173
+ _initSwiper(uniqueSelector, options, element);
143
174
  }
144
175
 
145
176
  // create the observer. It may init the swiper
146
177
  if (options.astro?.intersectionObserver) {
147
- _createObserver(uniqueClass, options, element);
178
+ _createObserver(uniqueSelector, options, element);
148
179
  }
149
180
  }
150
181
 
@@ -160,24 +191,32 @@ const {
160
191
  // Read the message from the data attribute.
161
192
  const options: AstroSwiperOptions = JSON.parse(this.dataset.options || '{}');
162
193
  // to have more than 1 swiper in a single page
163
- const uniqueClass = this.dataset.uniqueclass || '';
164
- const linkToThumbUniqueClass = this.dataset.linktothumbuniqueclass || '';
194
+ const uniqueSelector: selectorStringType = `.${this.dataset.uniqueclass}`;
195
+ const thumbSwiperUniqueSelector = options.astro?.thumbSwiperUniqueSelector;
165
196
 
166
197
  // no thumbnail link, or link to thumbnail swiper already created,
167
198
  // the swiper can be created or not immediatly depending on the observer option
168
- if (!linkToThumbUniqueClass || _useSwiper[linkToThumbUniqueClass]) {
169
- if (linkToThumbUniqueClass) {
170
- options.thumbs = { swiper: _useSwiper[linkToThumbUniqueClass], ...options.thumbs };
199
+ if (
200
+ !thumbSwiperUniqueSelector ||
201
+ getSwiperFromUniqueSelector(thumbSwiperUniqueSelector, getSwiperFromUniqueSelectorOptions)
202
+ ) {
203
+ if (thumbSwiperUniqueSelector) {
204
+ options.thumbs = {
205
+ swiper: getSwiperFromUniqueSelector(
206
+ thumbSwiperUniqueSelector,
207
+ getSwiperFromUniqueSelectorOptions,
208
+ ),
209
+ ...options.thumbs,
210
+ };
171
211
  }
172
212
  // create the swiper and the observer if needed
173
- _createSwiperAndObserver(uniqueClass, options, this);
213
+ _createSwiperAndObserver(uniqueSelector, options, this);
174
214
  } else {
175
215
  // cannot create the swiper as the thumbnail swiper not created yet
176
216
  // is delayed until the thumbnail swiper is initialized.
177
- _useDelaySwiper[uniqueClass] = linkToThumbUniqueClass;
217
+ _useDelaySwiper[uniqueSelector] = thumbSwiperUniqueSelector;
218
+ _useOptions[uniqueSelector] = options;
178
219
  }
179
-
180
- _useOptions[uniqueClass] = options;
181
220
  }
182
221
  }
183
222
 
package/src/index.ts CHANGED
@@ -4,6 +4,9 @@
4
4
  import type { Swiper, SwiperOptions } from 'swiper/types';
5
5
  import type { HTMLAttributes } from 'astro/types';
6
6
 
7
+ // type of a string that starts with a dot (class selector) or a hash (id selector), followed by any string
8
+ export type selectorStringType = `.${string}` | `#${string}`;
9
+
7
10
  /** Swiper options for the Astro component.
8
11
  * Basically the same as the original SwiperOptions, but extended
9
12
  * with new capabilities
@@ -26,7 +29,23 @@ export interface AstroSwiperOptions extends SwiperOptions {
26
29
  /** options for the IntersectionObserver */
27
30
  options?: IntersectionObserverInit;
28
31
  };
29
- /** TODO: uniqueClass and linkToThumbUniqueClass may be part of it */
32
+
33
+ /** useCustomElement, if true, the component will be rendered as a custom element, otherwise as a div.
34
+ * This option is true by default to keep legacy.
35
+ * It is there to be as close as possible to the original swiper structure, that is a div with class "swiper"
36
+ * and not a custom element.
37
+ * It is also to avoid issues with some swiper modules that are looking for the "swiper" class on the parent
38
+ * element, and not on the custom element.
39
+ */
40
+ useCustomElement?: boolean;
41
+
42
+ /** unique selector of the thumbnail swiper to link with, when using the thumbs module.
43
+ * when a thumbnail swiper is build, this parameter is provided on the main slider
44
+ * (the one with big slides, not the one to track the progress) and equal
45
+ * the unique selector of the thumbnail swiper (the one to track the progress).
46
+ * It is used to link the main swiper with the thumbnail swiper when using the thumbs module.
47
+ */
48
+ thumbSwiperUniqueSelector?: selectorStringType;
30
49
  };
31
50
  }
32
51
 
@@ -40,28 +59,17 @@ export interface AstroSwiperType extends HTMLAttributes<'div'> {
40
59
  */
41
60
  options?: AstroSwiperOptions;
42
61
 
43
- /** unique class to be able to retrieve the swiper instance, if required
44
- * Mandatory on thumbnail for example
45
- * When undefined, an automatic unique class name is provided
46
- */
62
+ /** add the default swiper class, true by default */
63
+ addDefaultClass?: boolean;
64
+
65
+ /** @deprecated is not really usefull anymore. If a specific unique class or id is needed,
66
+ * add it as an id or or a class directly */
47
67
  uniqueClass?: string;
48
68
 
49
- /** a thumbnail slider is build, this parameter is provided on the main slider
50
- * (the one with big slides, not the one to track the progress) and equal
51
- * the unique class of the thumbnail slider
52
- */
69
+ /** @deprecated use astro.options.astro.thumbsSwiperUniqueSelector instead */
53
70
  linkToThumbUniqueClass?: string;
54
71
 
55
- /** add the default swiper class, true by default */
56
- addDefaultClass?: boolean;
57
-
58
- /** useCustomElement, if true, the component will be rendered as a custom element, otherwise as a div.
59
- * This option is true by default to keep legacy.
60
- * It is there to be as close as possible to the original swiper structure, that is a div with class "swiper"
61
- * and not a custom element.
62
- * It is also to avoid issues with some swiper modules that are looking for the "swiper" class on the parent
63
- * element, and not on the custom element.
64
- */
72
+ /** @deprecated use astro.useCustomElement instead */
65
73
  useCustomElement?: boolean;
66
74
  }
67
75
 
@@ -91,7 +99,10 @@ export function getSwiperFromUniqueClass(uniqueClass: string): Swiper | undefine
91
99
  * @example const swiper = getSwiperFromUniqueSelector('.my-unique-class')
92
100
  * const swiper = getSwiperFromUniqueSelector('#my-unique-id')
93
101
  */
94
- export function getSwiperFromUniqueSelector(uniqueSelector: string): Swiper | undefined {
102
+ export function getSwiperFromUniqueSelector(
103
+ uniqueSelector: selectorStringType,
104
+ options?: { mayBeUndefined?: boolean },
105
+ ): Swiper | undefined {
95
106
  if (!/^[.#]/.test(uniqueSelector)) {
96
107
  console.warn("Used selector doesn't contain class or ID selector sign");
97
108
  }
@@ -111,10 +122,16 @@ export function getSwiperFromUniqueSelector(uniqueSelector: string): Swiper | un
111
122
  const childElement = element.firstElementChild as AstroSwiper;
112
123
  if (childElement?.astroSwiper) return childElement.astroSwiper;
113
124
 
114
- console.warn(
115
- `astro-swiper: element found with selector "${uniqueSelector}" but no swiper instance found. ` +
116
- `Expected either a custom element with astroSwiper property or a <div/> containing such an element.`,
117
- );
125
+ if (!options?.mayBeUndefined) {
126
+ // set options.mayBeUndefined to true to avoid this warning when the swiper is not initialized yet,
127
+ // but will be in the future:
128
+ // for example when using thumbnails, the main swiper is created before the thumbnail swiper,
129
+ // so it is normal that it is not found at this moment)
130
+ console.warn(
131
+ `astro-swiper: element found with selector "${uniqueSelector}" but no swiper instance found. ` +
132
+ `Expected either a custom element with astroSwiper property or a <div/> containing such an element.`,
133
+ );
134
+ }
118
135
 
119
136
  return undefined;
120
137
  }