@natachah/vanilla-frontend 0.1.13 → 0.1.15

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/docs/main.js CHANGED
@@ -24,7 +24,9 @@ if (current.startsWith('/pages/')) document.querySelectorAll(`#sidebar a[href*="
24
24
  // My awsome sidebar !!!
25
25
  import Drawer from './../js/_drawer.js'
26
26
  const sidebar = document.getElementById('sidebar')
27
- if (sidebar) new Drawer(sidebar)
27
+ if (sidebar) new Drawer(sidebar, {
28
+ cookie: 'demo-confort'
29
+ })
28
30
 
29
31
  // Code group
30
32
  import Tabpanel from './../js/_tabpanel.js'
@@ -96,7 +96,7 @@
96
96
  <p>To make them full width add the class <code>.flush</code></p>
97
97
 
98
98
  <doc-demo>
99
- <div class="card">
99
+ <div class="card" style="--card-border-color:#000;">
100
100
  <h3>Mycard</h3>
101
101
  <p>Content of the card</p>
102
102
  <div class="group flush">
@@ -105,6 +105,7 @@
105
105
  </div>
106
106
  <p>Content of the card</p>
107
107
  <ul class="list flush">
108
+ <li><a href="#" role="button">List F</a></li>
108
109
  <li>List D</li>
109
110
  <li><a>List E</a></li>
110
111
  <li><span>List F</span><button>Button</button></li>
@@ -114,7 +115,7 @@
114
115
  </doc-demo>
115
116
 
116
117
  <doc-code>
117
- <div class="card">
118
+ <div class="card" style="--card-border-color:#000">
118
119
  <h3>Mycard</h3>
119
120
  <p>Content of the card</p>
120
121
  <div class="group flush">
@@ -151,7 +152,7 @@
151
152
  </doc-code>
152
153
  <doc-code id="scss" data-type="scss" role="tabpanel">
153
154
  $outline-variations: (
154
- card
155
+ card
155
156
  );
156
157
  </doc-code>
157
158
  </div>
@@ -176,7 +177,7 @@
176
177
  </doc-code>
177
178
  <doc-code id="scss" data-type="scss" role="tabpanel">
178
179
  $color-variations: (
179
- card: (primary)
180
+ card: (primary)
180
181
  );
181
182
  </doc-code>
182
183
  </div>
@@ -57,7 +57,7 @@
57
57
  <doc-code id="js" data-type="js" role="tabpanel">
58
58
  import Drawer from '@natachah/vanilla-frontend/js/utilities/_drawer.js'
59
59
  const drawer = document.getElementById('drawer')
60
- if (drawer) new Drawer(drawer, { breakpoint : 960 })
60
+ if (drawer) new Drawer(drawer, { breakpoint : 960, cookie: 'name-of-my-cookie' })
61
61
  </doc-code>
62
62
  </div>
63
63
 
@@ -114,6 +114,10 @@
114
114
  <p>This documentation use the drawer as an exemple for the sidebar on the left !</p>
115
115
  </blockquote>
116
116
 
117
+ <blockquote class="warning">
118
+ <p>If your website use the <b>Comfort</b> JS component, you should use the same cookie name for both as it will combine the values.</p>
119
+ </blockquote>
120
+
117
121
  </doc-layout>
118
122
  <script type="module" src="/main.js"></script>
119
123
  </body>
@@ -14,7 +14,7 @@
14
14
  <p>The slider is using the a <code>&lt;div&gt;</code> tag with the class <code>.slider</code>.</p>
15
15
  <p>Each slide must be a <code>&lt;div&gt;</code> with <code>role=&quot;tabpanel&quot;</code> and <code>aria-hidden=&quot;true&quot;</code> attributes.</p>
16
16
  <doc-demo>
17
- <div id="slider" class="slider demo-slider">
17
+ <div id="sliderFull" class="slider demo-slider">
18
18
  <div id="slide1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one" alt="Image 1"></div>
19
19
  <div id="slide2" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=two" alt="Image 2"></div>
20
20
  <div id="slide3" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=three" alt="Image 3"></div>
@@ -22,15 +22,25 @@
22
22
  <div id="slide5" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=five" alt="Image 5"></div>
23
23
  <div id="slide6" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=six" alt="Image 6"></div>
24
24
  </div>
25
+ <button aria-controls="sliderFull" data-slider-prev>previous</button>
26
+ <div aria-controls="sliderFull" role="tablist">
27
+ <button role="tab" aria-controls="slide1" aria-selected="true">1</button>
28
+ <button role="tab" aria-controls="slide2" aria-selected="false">2</button>
29
+ <button role="tab" aria-controls="slide3" aria-selected="false">3</button>
30
+ <button role="tab" aria-controls="slide4" aria-selected="false">4</button>
31
+ <button role="tab" aria-controls="slide5" aria-selected="false">5</button>
32
+ <button role="tab" aria-controls="slide6" aria-selected="false">6</button>
33
+ </div>
34
+ <button aria-controls="sliderFull" data-slider-next>next</button>
25
35
  </doc-demo>
26
36
  <div class="code-group">
27
37
  <div role="tablist">
28
- <button role="tab" aria-controls="html">HTML</button>
38
+ <button role="tab" aria-controls="html" aria-selected="true">HTML</button>
29
39
  <button role="tab" aria-controls="scss">SCSS</button>
30
40
  <button role="tab" aria-controls="css">CSS</button>
31
41
  <button role="tab" aria-controls="js">JS</button>
32
42
  </div>
33
- <doc-code id="html" data-type="html" role="tabpanel">
43
+ <doc-code id="html" data-type="html" role="tabpanel" aria-hidden="false">
34
44
  <div id="slider" class="slider">
35
45
  <div id="slide1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one" alt="Image 1"></div>
36
46
  <div id="slide2" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=two" alt="Image 2"></div>
@@ -39,6 +49,16 @@
39
49
  <div id="slide5" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=five" alt="Image 5"></div>
40
50
  <div id="slide6" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=six" alt="Image 6"></div>
41
51
  </div>
52
+ <button aria-controls="slider" data-slider-prev>previous</button>
53
+ <div aria-controls="slider" role="tablist">
54
+ <button role="tab" aria-controls="slide1" aria-selected="true">1</button>
55
+ <button role="tab" aria-controls="slide2" aria-selected="false">2</button>
56
+ <button role="tab" aria-controls="slide3" aria-selected="false">3</button>
57
+ <button role="tab" aria-controls="slide4" aria-selected="false">4</button>
58
+ <button role="tab" aria-controls="slide5" aria-selected="false">5</button>
59
+ <button role="tab" aria-controls="slide6" aria-selected="false">6</button>
60
+ </div>
61
+ <button aria-controls="slider" data-slider-next>next</button>
42
62
  </doc-code>
43
63
  <doc-code id="scss" data-type="scss" role="tabpanel">
44
64
  @use '@natachah/vanilla-frontend/scss/components/slider';
@@ -50,31 +70,14 @@
50
70
  <doc-code id="js" data-type="js" role="tabpanel">
51
71
  import Slider from "@natachah/vanilla-frontend/js/_slider"
52
72
  const slider = document.getElementById('slider')
53
- if (slider) const mySliderObj = new Slider(sliderFade)
73
+ if (slider) const mySliderObj = new Slider(slider, {loop: true})
54
74
  </doc-code>
55
75
  </div>
56
76
 
57
77
  <h2>Indicators</h2>
58
78
  <p>You can create some indicators with a <code>&lt;div&gt;</code> tag with the <code>aria-controls=&quot;IdOfSlider&quot;</code> and <code>role=&quot;tablist&quot;</code> attributes.</p>
59
79
  <p>Inside you must insert each slides indicators as <code>&lt;button&gt;</code> tag with <code>role=&quot;tab&quot;</code>, <code>aria-controls=&quot;IdOfSlide&quot;</code> and <code>aria-selected=&quot;false&quot;</code> attributes.</p>
60
- <doc-demo>
61
- <div id="sliderTabs" class="slider demo-slider">
62
- <div id="slide1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one" alt="Image 1"></div>
63
- <div id="slide2" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=two" alt="Image 2"></div>
64
- <div id="slide3" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=three" alt="Image 3"></div>
65
- <div id="slide4" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=four" alt="Image 4"></div>
66
- <div id="slide5" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=five" alt="Image 5"></div>
67
- <div id="slide6" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=six" alt="Image 6"></div>
68
- </div>
69
- <div aria-controls="sliderTabs" role="tablist">
70
- <button role="tab" aria-controls="slide1" aria-selected="true">1</button>
71
- <button role="tab" aria-controls="slide2" aria-selected="false">2</button>
72
- <button role="tab" aria-controls="slide3" aria-selected="false">3</button>
73
- <button role="tab" aria-controls="slide4" aria-selected="false">4</button>
74
- <button role="tab" aria-controls="slide5" aria-selected="false">5</button>
75
- <button role="tab" aria-controls="slide6" aria-selected="false">6</button>
76
- </div>
77
- </doc-demo>
80
+
78
81
  <doc-code>
79
82
  <div aria-controls="slider" role="tablist">
80
83
  <button role="tab" aria-controls="slide1" aria-selected="true">1</button>
@@ -88,18 +91,6 @@
88
91
 
89
92
  <h2>Navigation</h2>
90
93
  <p>You can create some prev/next navigation with some <code>&lt;button&gt;</code> tag with the <code>aria-controls=&quot;IdOfSlider&quot;</code> and <code>data-slider-prev</code> or <code>data-slider-next</code> attributes.</p>
91
- <doc-demo>
92
- <div id="sliderNav" class="slider demo-slider">
93
- <div id="slide1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one" alt="Image 1"></div>
94
- <div id="slide2" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=two" alt="Image 2"></div>
95
- <div id="slide3" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=three" alt="Image 3"></div>
96
- <div id="slide4" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=four" alt="Image 4"></div>
97
- <div id="slide5" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=five" alt="Image 5"></div>
98
- <div id="slide6" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=six" alt="Image 6"></div>
99
- </div>
100
- <button aria-controls="sliderNav" data-slider-prev>previous</button>
101
- <button aria-controls="sliderNav" data-slider-next>next</button>
102
- </doc-demo>
103
94
  <doc-code>
104
95
  <button aria-controls="slider" data-slider-prev>previous</button>
105
96
  <button aria-controls="slider" data-slider-next>next</button>
@@ -108,14 +99,11 @@
108
99
  <h2>Variants</h2>
109
100
  <h3>Fade effect</h3>
110
101
  <p>You can change the CSS and JS to create a sort of fade effect, but it's not optimal.</p>
111
- <blockquote class="todo">
112
- <p>This functionality is not working good on mobile and with prev/next arrow.</p>
113
- </blockquote>
114
102
  <doc-demo>
115
- <div id="sliderFade" class="slider slider-fade-demo">
116
- <div id="slide7" role="tabpanel" aria-hidden="false"><img src="https://picsum.photos/id/220/400/330" srcset="https://picsum.photos/id/220/800/660 2x" alt="My random image from lorem picsum"></div>
117
- <div id="slide8" role="tabpanel" aria-hidden="true"><img src="https://picsum.photos/id/221/400/330" srcset="https://picsum.photos/id/221/800/660 2x" alt="My random image from lorem picsum"></div>
118
- <div id="slide9" role="tabpanel" aria-hidden="true"><img src="https://picsum.photos/id/222/400/330" srcset="https://picsum.photos/id/222/800/660 2x" alt="My random image from lorem picsum"></div>
103
+ <div id="sliderFade" class="slider slider-fade-demo" style="background-image: url(https://fakeimg.pl/760x506/?text=one);">
104
+ <div id="slide1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one" alt="Image 1"></div>
105
+ <div id="slide2" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=two" alt="Image 2"></div>
106
+ <div id="slide3" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=three" alt="Image 3"></div>
119
107
  </div>
120
108
  </doc-demo>
121
109
  <div class="code-group">
@@ -125,29 +113,29 @@
125
113
  <button role="tab" aria-controls="js">JS</button>
126
114
  </div>
127
115
  <doc-code id="html" data-type="html" role="tabpanel">
128
- <div id="mySlider" class="slider slider-fade-demo">
129
- <div id="slide7" role="tabpanel" aria-hidden="false"><img src="https://picsum.photos/id/220/400/330" srcset="https://picsum.photos/id/220/800/660 2x" alt="My random image from lorem picsum"></div>
130
- <div id="slide8" role="tabpanel" aria-hidden="true"><img src="https://picsum.photos/id/221/400/330" srcset="https://picsum.photos/id/221/800/660 2x" alt="My random image from lorem picsum"></div>
131
- <div id="slide9" role="tabpanel" aria-hidden="true"><img src="https://picsum.photos/id/222/400/330" srcset="https://picsum.photos/id/222/800/660 2x" alt="My random image from lorem picsum"></div>
116
+ <div id="sliderFade" class="slider slider-fade-demo" style="background-image: url(https://fakeimg.pl/760x506/?text=one);">
117
+ <div id="slide1" role="tabpanel" aria-hidden="false"><img src="https://fakeimg.pl/760x506/?text=one" alt="Image 1"></div>
118
+ <div id="slide2" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=two" alt="Image 2"></div>
119
+ <div id="slide3" role="tabpanel" aria-hidden="true"><img src="https://fakeimg.pl/760x506/?text=three" alt="Image 3"></div>
132
120
  </div>
133
121
  </doc-code>
134
122
  <doc-code id="css" data-type="css" role="tabpanel">
135
123
  .slider-fade-demo {
136
- --image-width: 100%;
137
- --image-ratio: 4/3;
138
- background-position: center;
139
- background-repeat: no-repeat;
140
- background-size: cover;
141
- > * {
142
- transition: all 2s ease-out;
143
- &[aria-hidden=true] {
144
- filter: blur(1rem);
145
- opacity: 0;
146
- }
147
- &[aria-hidden=false] {
148
- opacity: 1;
149
- }
150
- }
124
+ --image-width: 100%;
125
+ --image-ratio: 4/3;
126
+ background-position: center;
127
+ background-repeat: no-repeat;
128
+ background-size: cover;
129
+ > * {
130
+ transition: all 2s ease-out;
131
+ &[aria-hidden=true] {
132
+ filter: blur(1rem);
133
+ opacity: 0;
134
+ }
135
+ &[aria-hidden=false] {
136
+ opacity: 1;
137
+ }
138
+ }
151
139
  }
152
140
  </doc-code>
153
141
  <doc-code id="js" data-type="js" role="tabpanel">
@@ -155,16 +143,16 @@
155
143
  const sliderFade = document.getElementById('mySlider')
156
144
  if (sliderFade) {
157
145
 
158
- const mySliderObj = new Slider(sliderFade, {
159
- behavior: 'instant',
160
- autoplay: 4000
161
- })
146
+ const mySliderObj = new Slider(sliderFade, {
147
+ behavior: 'instant',
148
+ autoplay: 4000
149
+ })
162
150
 
163
- sliderFade.addEventListener('slider:changing', (ev) => {
164
- const currentSlide = mySliderObj._slides[ev.detail.current]
165
- const src = currentSlide.querySelector('img').getAttribute('src')
166
- sliderFade.style.backgroundImage = `url("${src}")`
167
- })
151
+ sliderFade.addEventListener('slider:changing', (ev) => {
152
+ const currentSlide = mySliderObj._slides[ev.detail.previous]
153
+ const src = currentSlide.querySelector('img').getAttribute('src')
154
+ sliderFade.style.backgroundImage = `url("${src}")`
155
+ })
168
156
 
169
157
  }
170
158
  </doc-code>
@@ -221,9 +209,9 @@
221
209
  </table>
222
210
  <doc-code data-type="js">
223
211
  new Slider(mySliderDiv, {
224
- behavior: 'smooth',
225
- loop: false,
226
- autoplay: false
212
+ behavior: 'smooth',
213
+ loop: false,
214
+ autoplay: false
227
215
  })
228
216
  </doc-code>
229
217
 
@@ -273,17 +261,6 @@
273
261
  </tr>
274
262
  </thead>
275
263
  <tbody>
276
- <tr>
277
- <td data-label="Event">
278
- <p>slider:changing</p>
279
- </td>
280
- <td data-label="Description">
281
- <p>This event is fired when the slide is changing</p>
282
- </td>
283
- <td data-label="Value">
284
- <p><code>current</code> as a <code>index number</code></p>
285
- </td>
286
- </tr>
287
264
  <tr>
288
265
  <td data-label="Event">
289
266
  <p>slider:changed</p>
@@ -299,8 +276,8 @@
299
276
  </table>
300
277
  <doc-code data-type="js">
301
278
  document.getElementById('mySliderId').addEventListener('slider:changed', (e) => {
302
- const theSlide = e.detail.current
303
- ...
279
+ const theSlide = e.detail.current
280
+ ...
304
281
  })
305
282
  </doc-code>
306
283
 
@@ -27,17 +27,24 @@ const dropdowns = document.querySelectorAll('.demo-dropdown')
27
27
  if (dropdowns) dropdowns.forEach(dropdown => new Dropdown(dropdown))
28
28
 
29
29
  import Slider from './../../../js/_slider.js'
30
- const sliders = document.querySelectorAll('.demo-slider')
31
- if (sliders) sliders.forEach(slider => new Slider(slider))
30
+ //if (sliders) sliders.forEach(slider => new Slider(slider))
31
+ const sliderFull = document.getElementById('sliderFull')
32
+ if (sliderFull) new Slider(sliderFull, {
33
+ //behavior: 'instant',
34
+ loop: true,
35
+ //autoplay: 1500
36
+ })
32
37
 
33
38
  const sliderFade = document.getElementById('sliderFade')
34
39
  if (sliderFade) {
35
40
  const mySliderObj = new Slider(sliderFade, {
36
41
  behavior: 'instant',
42
+ loop: true,
37
43
  autoplay: 4000
38
44
  })
39
- sliderFade.addEventListener('slider:changing', (ev) => {
40
- const src = mySliderObj._slides[ev.detail.current].querySelector('img').getAttribute('src')
45
+ sliderFade.addEventListener('slider:changed', (ev) => {
46
+ console.log(ev)
47
+ const src = mySliderObj._slides[ev.detail.previous].querySelector('img').getAttribute('src')
41
48
  sliderFade.style.backgroundImage = `url("${src}")`
42
49
  })
43
50
  }
@@ -18,7 +18,7 @@ class DocLayout extends HTMLElement {
18
18
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pin-angle" viewBox="0 0 16 16">
19
19
  <path d="M9.828.722a.5.5 0 0 1 .354.146l4.95 4.95a.5.5 0 0 1 0 .707c-.48.48-1.072.588-1.503.588-.177 0-.335-.018-.46-.039l-3.134 3.134a6 6 0 0 1 .16 1.013c.046.702-.032 1.687-.72 2.375a.5.5 0 0 1-.707 0l-2.829-2.828-3.182 3.182c-.195.195-1.219.902-1.414.707s.512-1.22.707-1.414l3.182-3.182-2.828-2.829a.5.5 0 0 1 0-.707c.688-.688 1.673-.767 2.375-.72a6 6 0 0 1 1.013.16l3.134-3.133a3 3 0 0 1-.04-.461c0-.43.108-1.022.589-1.503a.5.5 0 0 1 .353-.146m.122 2.112v-.002zm0-.002v.002a.5.5 0 0 1-.122.51L6.293 6.878a.5.5 0 0 1-.511.12H5.78l-.014-.004a5 5 0 0 0-.288-.076 5 5 0 0 0-.765-.116c-.422-.028-.836.008-1.175.15l5.51 5.509c.141-.34.177-.753.149-1.175a5 5 0 0 0-.192-1.054l-.004-.013v-.001a.5.5 0 0 1 .12-.512l3.536-3.535a.5.5 0 0 1 .532-.115l.096.022c.087.017.208.034.344.034q.172.002.343-.04L9.927 2.028q-.042.172-.04.343a1.8 1.8 0 0 0 .062.46z"/>
20
20
  </svg>
21
- 0.1.13
21
+ 0.1.15
22
22
  </span>
23
23
  </li>
24
24
  <li>
package/js/_drawer.js CHANGED
@@ -31,6 +31,7 @@ export default class Drawer extends BaseComponent {
31
31
  constructor(el, options = {}) {
32
32
 
33
33
  if (options.breakpoint && typeof options.breakpoint !== 'number') throw new Error(ErrorMessage.typeOf('options.breakpoint', 'number'))
34
+ if (options.cookie && typeof options.cookie !== 'string') throw new Error(ErrorMessage.typeOf('options.cookie', 'string'))
34
35
 
35
36
  // Run the SUPER constructor from BaseComponent
36
37
  super(el, options, 'drawer')
@@ -60,53 +61,52 @@ export default class Drawer extends BaseComponent {
60
61
  */
61
62
  #init() {
62
63
 
63
- const isOpenValue = window.innerWidth > this._options.breakpoint && !this._isOpen
64
+ // Set the cookie by default
65
+ if (this._cookie && !this._cookie.has('drawer-is-open')) this._cookie.set({ ...this._cookie.value, 'drawer-is-open': this._isOpen })
64
66
 
65
- // Init the default cookie
66
- if (this._cookie && !this._cookie.has('open')) this._cookie.set({ 'open': isOpenValue })
67
+ // Define the default state on bigger screen
68
+ const shouldBeOpen = this._cookie ? this._cookie.get('drawer-is-open') : true
67
69
 
68
- // Init the default open or close
69
- if (!this._cookie || (this._cookie.get('open') && !this._isOpen)) this.toggle()
70
+ // Window is bigger than breakpoint
71
+ // -> Show/Hide the drawer by the cookie
72
+ if (window.innerWidth > this._options.breakpoint) this.toggle(shouldBeOpen)
70
73
 
71
- // On resize check if need to open/close the drawer
74
+ // Window is smaller than breakpoint
75
+ // -> Hide the drawer
76
+ if (window.innerWidth < this._options.breakpoint) this.toggle(false)
77
+
78
+ // On window resize
79
+ // -> Toggle the drawer
72
80
  window.onresize = () => {
73
81
  clearTimeout(this._timeout)
74
82
  this._timeout = setTimeout(() => {
75
- if ((window.innerWidth > this._options.breakpoint && !this._isOpen) || (window.innerWidth < this._options.breakpoint && this._isOpen)) {
76
- this.toggle()
77
- this.#resetCookie()
78
- }
83
+
84
+ // Bigger than breakpoint
85
+ if (window.innerWidth > this._options.breakpoint && (!this._isOpen && shouldBeOpen)) this.toggle(true)
86
+
87
+ // Smaller than breakpoint -> Invisible
88
+ if (window.innerWidth < this._options.breakpoint && this._isOpen) this.toggle(false)
89
+
79
90
  }, 250)
80
91
  }
81
92
 
82
93
  // On click on the button toggle the drawer
83
- this._buttons.forEach((button) => button.addEventListener('click', () => {
84
- this.toggle()
85
- if (window.innerWidth > this._options.breakpoint) this.#resetCookie()
86
- if (this._focus && this._isOpen) this._focus.focus()
87
- }))
94
+ this._buttons.forEach((button) => button.addEventListener('click', () => this.toggle()))
88
95
 
89
96
  // On click on the backdrop, close the drawer
90
97
  if (this._backdrop) this._backdrop.addEventListener('click', () => this.toggle())
91
98
 
92
99
  }
93
100
 
94
- /**
95
- * Reset the cookie
96
- *
97
- */
98
- #resetCookie() {
99
- if (this._cookie) this._cookie.set({ 'open': this._isOpen })
100
- }
101
-
102
101
  /**
103
102
  * Toggle the drawer
104
103
  *
104
+ * @param {boolean} value
105
105
  */
106
- toggle() {
106
+ toggle(value = !this._isOpen) {
107
107
 
108
108
  // Change the state
109
- this._isOpen = !this._isOpen
109
+ this._isOpen = value
110
110
 
111
111
  // Change the [aria-pressed] & [aria-expanded] attribute on the <button>
112
112
  this._buttons.forEach((button) => {
@@ -117,6 +117,14 @@ export default class Drawer extends BaseComponent {
117
117
  // Change the [hidden] attribute on the drawer
118
118
  this._element.hidden = !this._isOpen
119
119
 
120
+ // Change the cookie
121
+ if (this._cookie && (this._cookie.get('drawer-is-open') !== this._isOpen) && window.innerWidth > this._options.breakpoint) {
122
+ this._cookie.set({ ...this._cookie.value, 'drawer-is-open': this._isOpen })
123
+ }
124
+
125
+ // Add the focus if open
126
+ if (this._focus && this._isOpen) this._focus.focus()
127
+
120
128
  }
121
129
 
122
130
 
package/js/_slider.js CHANGED
@@ -2,12 +2,12 @@
2
2
  * ------------------------------------------------------------------
3
3
  * Slider
4
4
  * ------------------------------------------------------------------
5
- * This class enable the functionality to make an element slider
5
+ * This class enables the functionality to make an element slider
6
6
  *
7
7
  * @author Natacha Herth
8
8
  * @copyright Natacha Herth, design & web development
9
9
  *
10
- * * keep check on the scrollend event: https://caniuse.com/?search=scrollend
10
+ * Keep check on the scrollend event: https://caniuse.com/?search=scrollend
11
11
  */
12
12
 
13
13
  import BaseComponent from './utilities/_base-component'
@@ -16,34 +16,52 @@ import ErrorMessage from "./utilities/_error"
16
16
  export default class Slider extends BaseComponent {
17
17
 
18
18
  static OPTIONS = {
19
- behavior: 'smooth', // Can be auto, smooth or instant
19
+ behavior: 'smooth', // Can be auto, smooth, or instant
20
20
  loop: false,
21
21
  autoplay: false
22
22
  }
23
23
 
24
24
  /**
25
- * Creates an instance
25
+ * Creates an instance of Slider.
26
26
  *
27
27
  * @param {HTMLElement} el - The HTML element
28
- * @param {object} options - The custom options
28
+ * @param {object} options - Custom options
29
29
  * @constructor
30
30
  */
31
31
  constructor(el, options = {}) {
32
32
 
33
- // Check for errors
34
- if (options.behavior && !['auto', 'smooth', 'instant'].includes(options.behavior)) throw new Error(ErrorMessage.enumOf('options.behavior', 'auto|smooth|instant'))
35
- if (options.loop && typeof options.loop !== 'boolean') throw new Error(ErrorMessage.typeOf('options.loop', 'boolean'))
36
- if (options.autoplay && (typeof options.autoplay !== 'boolean' && typeof options.autoplay !== 'number')) throw new Error(ErrorMessage.typeOf('options.autoplay', 'boolean|number'))
33
+ // Check for errors in the options
34
+ if (options.behavior && !['auto', 'smooth', 'instant'].includes(options.behavior)) {
35
+ throw new Error(ErrorMessage.enumOf('options.behavior', 'auto|smooth|instant'))
36
+ }
37
+ if (options.loop && typeof options.loop !== 'boolean') {
38
+ throw new Error(ErrorMessage.typeOf('options.loop', 'boolean'))
39
+ }
40
+ if (options.autoplay && (typeof options.autoplay !== 'boolean' && typeof options.autoplay !== 'number')) {
41
+ throw new Error(ErrorMessage.typeOf('options.autoplay', 'boolean|number'))
42
+ }
37
43
 
38
44
  // Run the SUPER constructor from BaseComponent
39
45
  super(el, options, 'slider')
40
46
 
41
- // Reduce animation
42
- const isReduced = window.matchMedia(`(prefers-reduced-motion: reduce)`) === true || window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true
47
+ // Handle reduced motion preferences
48
+ const isReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches
43
49
  if (isReduced) this._options.behavior = 'instant'
44
50
 
45
- // If loop, clone first and last slides (needed in case or scrolling/grabbing and slide effect)
46
- if (this._options.loop) {
51
+ // Get slides and buttons
52
+ this._slides = Array.from(this._element.querySelectorAll('[role=tabpanel]'))
53
+
54
+ this._buttons = {
55
+ prev: document.querySelector(`[aria-controls=${this._element.id}][data-slider-prev]`),
56
+ next: document.querySelector(`[aria-controls=${this._element.id}][data-slider-next]`),
57
+ tabs: document.querySelectorAll(`[aria-controls=${this._element.id}][role=tablist] [role=tab]`)
58
+ }
59
+
60
+ this._current = 0
61
+ this._interval = null
62
+
63
+ // Clone first and last slides if loop is enabled
64
+ if (this._options.loop && this._options.behavior == 'smooth') {
47
65
 
48
66
  const cloneFirst = this._element.firstElementChild.cloneNode(true)
49
67
  const cloneLast = this._element.lastElementChild.cloneNode(true)
@@ -60,189 +78,152 @@ export default class Slider extends BaseComponent {
60
78
 
61
79
  }
62
80
 
63
- // Define the properties (don't use .children because of clones in loop)
64
- this._slides = this._element.querySelectorAll('[role=tabpanel]')
65
-
66
- this._buttons = {
67
- prev: document.querySelector(`[aria-controls=${this._element.id}][data-slider-prev]`),
68
- next: document.querySelector(`[aria-controls=${this._element.id}][data-slider-next]`),
69
- tabs: document.querySelectorAll(`[aria-controls=${this._element.id}][role=tablist] [role=tab]`)
70
- }
71
-
72
- this._current = 0
73
-
74
- this._interval = null
75
-
81
+ // Initialize event listeners and functionality
76
82
  this.#init()
77
-
78
83
  }
79
84
 
80
85
  /**
81
- * Init the event listener
86
+ * Initialize event listeners and autoplay functionality.
82
87
  *
83
88
  * @private
84
89
  */
85
90
  #init() {
86
91
 
87
- // AUTOPLAY
88
- if (this._options.autoplay) this._interval = setInterval(() => this.next(), this._options.autoplay)
92
+ // Handle autoplay
93
+ if (this._options.autoplay) {
94
+ this._interval = setInterval(() => this.next(), this._options.autoplay)
95
+ }
89
96
 
90
- // CLICK next
97
+ // Add event listeners for next and prev buttons
91
98
  if (this._buttons.next) this._buttons.next.addEventListener('click', () => this.next())
92
-
93
- // CLICK prev
94
99
  if (this._buttons.prev) this._buttons.prev.addEventListener('click', () => this.prev())
95
100
 
96
- // CLICK tabs
97
- if (this._buttons.tabs.length) this._buttons.tabs.forEach((tab, index) => tab.addEventListener('click', () => this.goTo(index)))
98
-
99
- // CLICK scroll
100
- this._element.addEventListener('scroll', () => {
101
-
102
- // Clear timeout to avoid multiple request
103
- clearTimeout(this._element.scrollTimeout)
104
-
105
- // Run event before changed
106
- this.emmitEvent('changing', { current: this._current })
107
-
108
- // Set the timeout
109
- this._element.scrollTimeout = setTimeout(() => {
110
-
111
- // Check loop on scrolling
112
- if (this._options.loop) this.#loop()
113
-
114
- // Toggle the attributes
115
- this.#change()
116
-
117
- }, 150)
101
+ // Add event listeners for tabs
102
+ if (this._buttons.tabs.length) {
103
+ this._buttons.tabs.forEach((tab, index) => tab.addEventListener('click', () => this.goTo(index)))
104
+ }
118
105
 
119
- // Make sure to reset the interval to keep the slide duration when manually change
120
- if (this._options.autoplay) {
106
+ // Handle autoplay reset after user interaction
107
+ if (this._options.autoplay) {
108
+ this._element.addEventListener('click', () => {
121
109
  clearInterval(this._interval)
122
110
  this._interval = setInterval(() => this.next(), this._options.autoplay)
123
- }
124
-
125
- })
126
-
127
- }
128
-
129
- /**
130
- * Change the current slide and toggle the attributes
131
- *
132
- * @private
133
- */
134
- #change() {
135
-
136
- // Define the index
137
- const index = this._slides.length - [...this._slides].reverse().findIndex((slide) => this._element.scrollLeft >= slide.offsetLeft) - 1
138
-
139
- // Check if index change to avoid multiple call
140
- if (index !== this._current) {
141
-
142
- // Define the new current
143
- this._current = index
144
-
145
- // Change the [aria-selected] attribute on tabs
146
- this._buttons.tabs.forEach((tab, index) => tab.setAttribute('aria-selected', index === this._current))
147
-
148
- // Change the [aria-hidden] attribute on slide
149
- this._slides.forEach((slide, index) => slide.setAttribute('aria-hidden', index !== this._current))
111
+ })
112
+ }
150
113
 
151
- // Toggle [disabled] attribute on the next button
152
- if (this._buttons.next && !this._options.loop) this._buttons.next.disabled = this._current === this._slides.length - 1
114
+ // Enable swipe functionality on touch devices.
115
+ if (!this._options.autoplay) {
116
+ let startX = 0
153
117
 
154
- // Toggle [disabled] attribute on the prev button
155
- if (this._buttons.prev && !this._options.loop) this._buttons.prev.disabled = this._current === 0
118
+ const onTouchStart = (event) => {
119
+ startX = event.touches[0].clientX
120
+ }
156
121
 
157
- // Run event after changed
158
- this.emmitEvent('changed', { current: this._current })
122
+ const onTouchEnd = (event) => {
123
+ const endX = event.changedTouches[0].clientX
124
+ if (startX > endX + 50) {
125
+ this.next()
126
+ } else if (startX < endX - 50) {
127
+ this.prev()
128
+ }
129
+ }
159
130
 
131
+ this._element.addEventListener('touchstart', onTouchStart)
132
+ this._element.addEventListener('touchend', onTouchEnd)
160
133
  }
161
-
162
134
  }
163
135
 
164
136
  /**
165
- * Loop scrolling when reach the start/end of the slide
137
+ * Go to a specific slide by index.
166
138
  *
167
- * @returns
168
- * @private
139
+ * @param {int} index - The index of the slide
169
140
  */
170
- #loop() {
141
+ goTo(index) {
171
142
 
172
- // Going to much left => go to the last slide
173
- if (this._element.scrollLeft <= this._element.offsetWidth) {
174
- this._element.scrollTo(this._slides[this._slides.length - 1].offsetLeft, 0)
175
- return
143
+ if (typeof index !== 'number') {
144
+ throw new Error(ErrorMessage.typeOf('index', 'number'))
176
145
  }
177
146
 
178
- // Going to much right => go to the first slide
179
- if (this._element.scrollWidth - this._element.scrollLeft <= this._element.offsetWidth) {
180
- this._element.scrollTo(this._slides[0].offsetLeft, 0)
181
- return
182
- }
147
+ const previous = this._current
183
148
 
184
- }
149
+ let clone
185
150
 
186
- /**
187
- * Go to a slide by index
188
- *
189
- * @param {int} index - The index number of the slide
190
- */
191
- goTo(index) {
151
+ if (this._options.loop && (index < 0 || index >= this._slides.length)) {
192
152
 
193
- // Check for errors
194
- if (typeof index !== 'number') throw new Error(ErrorMessage.typeOf('index', 'number'))
153
+ // Go to the correct slide index
154
+ this._current = index < 0 ? this._slides.length - 1 : 0
195
155
 
196
- // Define the offset, if loop get the first or last slide offset
197
- let offset
156
+ // If scroll behavior go to the clone offset
157
+ if (this._options.behavior == 'smooth') {
158
+ clone = this._current == 0 ? this._element.lastElementChild : this._element.firstElementChild
159
+ }
198
160
 
199
- if (this._options.loop && (index < 0 || index > this._slides.length - 1)) {
200
- offset = this._element.children[index + 1].offsetLeft
201
161
  } else {
202
- index = index < 0 ? this._slides.length - 1 : index % this._slides.length
203
- offset = this._slides[index].offsetLeft
162
+ // Otherwise go to the index
163
+ this._current = index
204
164
  }
205
165
 
206
- // Scroll to position
166
+ // Define the offset
167
+ const offset = clone ? clone.offsetLeft : this._slides[this._current].offsetLeft
168
+
169
+ // Go to the slide
207
170
  this._element.scrollTo({
208
171
  left: offset,
209
172
  behavior: this._options.behavior
210
173
  })
211
174
 
175
+ // If clone offset, then go to the right slide instant
176
+ if (clone) {
177
+ setTimeout(() => {
178
+ this._element.scrollTo({
179
+ left: this._slides[this._current].offsetLeft,
180
+ behavior: 'instant'
181
+ })
182
+ }, 500)
183
+ }
184
+
185
+ // Update the [aria-selected] attribute on tabs
186
+ this._buttons.tabs.forEach((tab, idx) => tab.setAttribute('aria-selected', idx === this._current))
187
+
188
+ // Update the [aria-hidden] attribute on slides
189
+ this._slides.forEach((slide, idx) => slide.setAttribute('aria-hidden', idx !== this._current))
190
+
191
+ // Disable next and prev buttons if necessary
192
+ if (this._buttons.next && !this._options.loop) {
193
+ this._buttons.next.disabled = this._current === this._slides.length - 1
194
+ }
195
+ if (this._buttons.prev && !this._options.loop) {
196
+ this._buttons.prev.disabled = this._current === 0
197
+ }
198
+
199
+ // Emit "changed" event after the slide has changed
200
+ this.emmitEvent('changed', { current: this._current, previous: previous })
212
201
  }
213
202
 
214
203
  /**
215
- * Go to the next slide
216
- *
204
+ * Go to the next slide.
217
205
  */
218
206
  next() {
207
+ const nextIndex = this._current + 1
219
208
 
220
- // Define the new _current
221
- const index = this._current + 1
222
-
223
- // If last item => return
224
- if (!this._options.loop && !this._options.autoplay && index === this._slides.length) return
225
-
226
- // Run method goTo()
227
- this.goTo(index)
209
+ // Prevent scrolling if at the last slide and looping is disabled
210
+ if (!this._options.loop && nextIndex >= this._slides.length) return
228
211
 
212
+ // Move to the next slide
213
+ this.goTo(nextIndex)
229
214
  }
230
215
 
231
216
  /**
232
- * Go to the previous slide
233
- *
217
+ * Go to the previous slide.
234
218
  */
235
219
  prev() {
220
+ const prevIndex = this._current - 1
236
221
 
237
- // Define the new _current
238
- const index = this._current - 1
239
-
240
- // If first item => return
241
- if (!this._options.loop && index < 0) return
242
-
243
- // Run method goTo()
244
- this.goTo(index)
222
+ // Prevent scrolling if at the first slide and looping is disabled
223
+ if (!this._options.loop && prevIndex < 0) return
245
224
 
225
+ // Move to the previous slide
226
+ this.goTo(prevIndex)
246
227
  }
247
228
 
248
- }
229
+ }
@@ -9,21 +9,18 @@
9
9
  * - Constructor: Return the correct properties
10
10
  * - #Init(): Loop will clone the first and last slide
11
11
  * - #Init(): Autoplay will emmit next() method every X ms
12
- * - #Init(): Scroll will change the current attributes
13
12
  * - #Init(): Click on <button> with [role=tab] emmit the goTo() method
14
13
  * - #Init(): Click on <button> with [data-slider-prev] emmit the prev() method
15
14
  * - #Init(): Click on <button> with [data-slider-next] emmit the next() method
16
15
  * - GoTo(): Passing the correct parameters
17
- * - GoTo(): Emit a scroll() method
16
+ * - GoTo(): Go to the first or last slide via toGo() method
17
+ * - GoTo(): Change the [aria-selected], [aria-hidden] and [disabled] attributes
18
+ * - GoTo(): Emmit the slider:changed events
18
19
  * - Prev(): Emmit the goTo() method with correct index
19
20
  * - Prev(): Don't emmit the goTo() method if already first slide
20
21
  * - Next(): Emmit the goTo() method with correct index
21
22
  * - Next(): Don't emmit the goTo() method if already last slide
22
- * - #Change(): Change the [aria-selected], [aria-hidden] and [disabled] attributes
23
- * - #Change(): Emmit the slider:changing and slider:changed events
24
- * - #Loop(): Go to the last slide if too much left
25
- * - #Loop(): Go to the first slide if too much right
26
- * - #Loop(): Go to the first or last slide via toGo() method
23
+
27
24
  */
28
25
 
29
26
  import { describe, test, expect, beforeAll, vi, afterAll } from "vitest"
@@ -33,12 +30,6 @@ import ErrorMessage from "../utilities/_error"
33
30
 
34
31
  let fakeDiv, fakeSlider, fakeDivLoop, fakeSliderLoop
35
32
 
36
- function setScroll(value = 0, el = fakeDiv) {
37
- Object.assign(el, { scrollLeft: value })
38
- fireEvent.scroll(el, { target: { scrollX: value } })
39
- vi.runAllTimers()
40
- }
41
-
42
33
  /**
43
34
  * Before all tests
44
35
  *
@@ -111,6 +102,7 @@ describe('Structure of the class', () => {
111
102
  })
112
103
 
113
104
  test('Constructor: Return the correct properties', () => {
105
+ console.log(document.querySelectorAll('#slider [role=tabpanel]') == fakeSlider._slides)
114
106
  expect(fakeSlider).toHaveProperty('_element')
115
107
  expect(fakeSlider).toHaveProperty('_options')
116
108
  expect(fakeSlider).toHaveProperty('_slides')
@@ -118,7 +110,7 @@ describe('Structure of the class', () => {
118
110
  expect(fakeSlider).toHaveProperty('_current')
119
111
  expect(fakeSlider).toHaveProperty('_interval')
120
112
  expect(fakeSlider._slides).toBeTypeOf('object')
121
- expect(fakeSlider._slides).toStrictEqual(document.querySelectorAll('#slider [role=tabpanel]'))
113
+ expect(fakeSlider._slides).toStrictEqual(Array.from(document.querySelectorAll('#slider [role=tabpanel]')))
122
114
  expect(fakeSlider._buttons).toBeTypeOf('object')
123
115
  expect(fakeSlider._buttons.prev).toBeTypeOf('object')
124
116
  expect(fakeSlider._buttons.next).toBeTypeOf('object')
@@ -150,12 +142,6 @@ describe('#Init()', () => {
150
142
  clearInterval(fakeSliderAuto._interval)
151
143
  })
152
144
 
153
- test('Scroll will change the current attributes', () => {
154
- expect(fakeSlider._current).toBe(0)
155
- setScroll(100)
156
- expect(fakeSlider._current).toBe(1)
157
- })
158
-
159
145
  test('Click on <button> with [role=tab] emmit the goTo() method', () => {
160
146
  const fakeTab = fakeSlider._buttons.tabs[0]
161
147
  const methodSpy = vi.spyOn(fakeSlider, 'goTo')
@@ -185,22 +171,62 @@ describe('GoTo()', () => {
185
171
  expect(() => fakeSlider.goTo()).toThrowError(ErrorMessage.typeOf('index', 'number'))
186
172
  })
187
173
 
188
- test('Emit a scroll() method', () => {
189
- const scrollSpy = vi.spyOn(fakeDiv, 'scroll')
174
+ test('Toggle the [aria-selected], [aria-hidden] and [disabled] attributes', () => {
190
175
  fakeSlider.goTo(0)
176
+ expect(fakeSlider._current).toBe(0)
177
+ expect(fakeSlider._slides[0].getAttribute('aria-hidden')).toBe('false')
178
+ expect(fakeSlider._buttons.tabs[0].getAttribute('aria-selected')).toBe('true')
179
+ expect(fakeSlider._buttons.prev.hasAttribute('disabled')).toBeTruthy()
180
+ fakeSlider.goTo(1)
181
+ expect(fakeSlider._current).toBe(1)
182
+ expect(fakeSlider._slides[0].getAttribute('aria-hidden')).toBe('true')
183
+ expect(fakeSlider._slides[1].getAttribute('aria-hidden')).toBe('false')
184
+ expect(fakeSlider._buttons.tabs[0].getAttribute('aria-selected')).toBe('false')
185
+ expect(fakeSlider._buttons.tabs[1].getAttribute('aria-selected')).toBe('true')
186
+ expect(fakeSlider._buttons.prev.hasAttribute('disabled')).toBeFalsy()
187
+ fakeSlider.goTo(2)
188
+ expect(fakeSlider._current).toBe(2)
189
+ expect(fakeSlider._slides[1].getAttribute('aria-hidden')).toBe('true')
190
+ expect(fakeSlider._slides[2].getAttribute('aria-hidden')).toBe('false')
191
+ expect(fakeSlider._buttons.tabs[1].getAttribute('aria-selected')).toBe('false')
192
+ expect(fakeSlider._buttons.tabs[2].getAttribute('aria-selected')).toBe('true')
193
+ expect(fakeSlider._buttons.next.hasAttribute('disabled')).toBeTruthy()
194
+ })
195
+
196
+ test('Go to the first or last slide via toGo() method', () => {
197
+
198
+ const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
199
+
200
+ fakeSliderLoop.goTo(-1)
201
+
191
202
  expect(scrollSpy).toHaveBeenCalledWith({
192
203
  behavior: "smooth",
193
204
  left: 0,
194
205
  }, undefined)
206
+
207
+ fakeSliderLoop.goTo(3)
208
+
209
+ expect(scrollSpy).toHaveBeenCalledWith({
210
+ behavior: "smooth",
211
+ left: 400,
212
+ }, undefined)
213
+
214
+ })
215
+
216
+ test('Emmit the slider:changed events', () => {
217
+ const eventSpy = vi.spyOn(fakeSlider, 'emmitEvent')
218
+ fakeSlider.goTo(0)
219
+ expect(eventSpy).toHaveBeenCalledWith('changed', { current: 0, previous: 2 })
195
220
  })
196
221
 
197
222
  })
198
223
 
199
224
  describe('Prev()', () => {
200
225
 
201
- afterAll(() => setScroll())
226
+ afterAll(() => fakeSlider.goTo(0))
202
227
 
203
228
  test('Emit a goTo() method with correct index', () => {
229
+ fakeSlider.goTo(1)
204
230
  const methodSpy = vi.spyOn(fakeSlider, 'goTo')
205
231
  fakeSlider.prev()
206
232
  expect(methodSpy).toHaveBeenCalledWith(0)
@@ -217,7 +243,7 @@ describe('Prev()', () => {
217
243
 
218
244
  describe('Next()', () => {
219
245
 
220
- afterAll(() => setScroll())
246
+ afterAll(() => fakeSlider.goTo(0))
221
247
 
222
248
  test('Emit a goTo() method and index is X', () => {
223
249
  const methodSpy = vi.spyOn(fakeSlider, 'goTo')
@@ -232,76 +258,4 @@ describe('Next()', () => {
232
258
  expect(methodSpy).not.toHaveBeenCalled()
233
259
  })
234
260
 
235
- })
236
-
237
- describe('#Change()', () => {
238
-
239
- test('Toggle the [aria-selected], [aria-hidden] and [disabled] attributes', () => {
240
- expect(fakeSlider._current).toBe(0)
241
- expect(fakeSlider._slides[0].getAttribute('aria-hidden')).toBe('false')
242
- expect(fakeSlider._buttons.tabs[0].getAttribute('aria-selected')).toBe('true')
243
- expect(fakeSlider._buttons.prev.hasAttribute('disabled')).toBeTruthy()
244
- setScroll(100)
245
- expect(fakeSlider._current).toBe(1)
246
- expect(fakeSlider._slides[0].getAttribute('aria-hidden')).toBe('true')
247
- expect(fakeSlider._slides[1].getAttribute('aria-hidden')).toBe('false')
248
- expect(fakeSlider._buttons.tabs[0].getAttribute('aria-selected')).toBe('false')
249
- expect(fakeSlider._buttons.tabs[1].getAttribute('aria-selected')).toBe('true')
250
- expect(fakeSlider._buttons.prev.hasAttribute('disabled')).toBeFalsy()
251
- setScroll(200)
252
- expect(fakeSlider._current).toBe(2)
253
- expect(fakeSlider._slides[1].getAttribute('aria-hidden')).toBe('true')
254
- expect(fakeSlider._slides[2].getAttribute('aria-hidden')).toBe('false')
255
- expect(fakeSlider._buttons.tabs[1].getAttribute('aria-selected')).toBe('false')
256
- expect(fakeSlider._buttons.tabs[2].getAttribute('aria-selected')).toBe('true')
257
- expect(fakeSlider._buttons.next.hasAttribute('disabled')).toBeTruthy()
258
- })
259
-
260
- test('Emmit the slider:changing and slider:changed events', () => {
261
- const eventSpy = vi.spyOn(fakeSlider, 'emmitEvent')
262
- setScroll(0)
263
- expect(eventSpy).toHaveBeenCalledWith('changing', { current: 2 })
264
- expect(eventSpy).toHaveBeenCalledWith('changed', { current: 0 })
265
- })
266
-
267
- })
268
-
269
- describe('#Loop()', () => {
270
-
271
- test('Go to the last slide if too much left', () => {
272
- const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
273
- expect(fakeSliderLoop._current).toBe(0)
274
- setScroll(0, fakeDivLoop)
275
- expect(fakeSliderLoop._current).toBe(2)
276
- expect(scrollSpy).toHaveBeenCalledWith(300, 0)
277
- })
278
-
279
- test('Go to the first slide if too much right', () => {
280
- const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
281
- expect(fakeSliderLoop._current).toBe(2)
282
- setScroll(400, fakeDivLoop)
283
- expect(fakeSliderLoop._current).toBe(0)
284
- expect(scrollSpy).toHaveBeenCalledWith(100, 0)
285
- })
286
-
287
- test('Go to the first or last slide via toGo() method', () => {
288
-
289
- const scrollSpy = vi.spyOn(fakeDivLoop, 'scroll')
290
-
291
- fakeSliderLoop.goTo(-1)
292
-
293
- expect(scrollSpy).toHaveBeenCalledWith({
294
- behavior: "smooth",
295
- left: 0,
296
- }, undefined)
297
-
298
- fakeSliderLoop.goTo(3)
299
-
300
- expect(scrollSpy).toHaveBeenCalledWith({
301
- behavior: "smooth",
302
- left: 400,
303
- }, undefined)
304
-
305
- })
306
-
307
261
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@natachah/vanilla-frontend",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
4
4
  "description": "A vanilla frontend framework",
5
5
  "keywords": [
6
6
  "html5",
@@ -62,6 +62,10 @@ $customCardProperties: map.merge(default.$item-properties, $customCard);
62
62
  border-bottom: var(--card-divider-size, var(--card-border-size, var(--border-size))) var(--card-divider-style, var(--card-border-style, var(--border-style))) var(--card-divider-color, var(--card-border-color, transparent));
63
63
  }
64
64
 
65
+ > .flush {
66
+ border-radius: 0;
67
+ }
68
+
65
69
  > picture.flush {
66
70
  max-width: inherit;
67
71
  overflow: hidden;
@@ -73,12 +77,12 @@ $customCardProperties: map.merge(default.$item-properties, $customCard);
73
77
 
74
78
  > .flush.list > * {
75
79
 
76
- &:not(:has(a[role=button]:only-child, button:only-child)),
77
- &:has(a[role=button]:only-child, button:only-child) > * {
80
+ border-inline: none !important;
81
+
82
+ &:has(> a[role=button]:only-child, > button:only-child) > * {
78
83
  border-inline: none !important;
79
84
  }
80
85
 
81
-
82
86
  &:first-child,
83
87
  &:first-child > :only-child {
84
88
  border-top: none !important;
@@ -93,8 +97,6 @@ $customCardProperties: map.merge(default.$item-properties, $customCard);
93
97
  border-end-end-radius: inherit !important;
94
98
  }
95
99
 
96
-
97
-
98
100
  }
99
101
 
100
102
  > .flush.group {
@@ -18,17 +18,18 @@
18
18
  grid-auto-flow: column;
19
19
  grid-auto-columns: calc((100% / var(--slider-columns, 1)) - var(--slider-gap, 0rem));
20
20
  gap: var(--slider-gap, 0);
21
- overscroll-behavior-inline: contain;
22
- overflow-x: auto;
23
- scroll-snap-type: inline mandatory;
21
+ overflow: hidden;
22
+ //overscroll-behavior-inline: contain;
23
+ //overflow-x: auto;
24
+ //scroll-snap-type: inline mandatory;
24
25
 
25
26
  // Remove Scrollbar
26
- scrollbar-width: none;
27
- -ms-overflow-style: none;
27
+ //scrollbar-width: none;
28
+ //-ms-overflow-style: none;
28
29
 
29
30
  > * {
30
- scroll-snap-align: start;
31
- scroll-padding-inline: 0;
31
+ //scroll-snap-align: start;
32
+ //scroll-padding-inline: 0;
32
33
  }
33
34
 
34
35
  }