@natachah/vanilla-frontend 0.1.15 → 0.1.17

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.
@@ -95,45 +95,27 @@
95
95
  </ul>
96
96
  </doc-code>
97
97
 
98
- <h2>Manually move</h2>
99
- <p>You can manually move the item by adding some button with <code>data-go="up"</code> or <code>data-go="down"</code> attribute</p>
100
- <doc-demo>
101
- <ul class="demo-sortable">
102
- <li draggable="false">
103
- <button data-go="up">UP</button><button data-go="down">Down</button>
104
- Lorem, ipsum.
105
- </li>
106
- <li draggable="false">
107
- <button data-go="up">UP</button><button data-go="down">Down</button>
108
- Impedit, quod!
109
- </li>
110
- <li draggable="false">
111
- <button data-go="up">UP</button><button data-go="down">Down</button>
112
- Repudiandae, rerum.
113
- </li>
114
- </ul>
115
- </doc-demo>
116
-
117
- <doc-code>
118
- <ul id="mySortableListWithBtn">
119
- <li draggable="false">
120
- <button data-go="up">UP</button><button data-go="down">Down</button>
121
- Lorem, ipsum.
122
- </li>
123
- <li draggable="false">
124
- <button data-go="up">UP</button><button data-go="down">Down</button>
125
- Impedit, quod!
126
- </li>
127
- <li draggable="false">
128
- <button data-go="up">UP</button><button data-go="down">Down</button>
129
- Repudiandae, rerum.
130
- </li>
131
- </ul>
132
- </doc-code>
133
-
134
-
135
98
  <h2 id="javascript">Javascript</h2>
136
99
  <p>To enable this component you need to import the javascript file and create a new Sortable object.</p>
100
+ <h3>Methods</h3>
101
+ <table>
102
+ <thead>
103
+ <tr>
104
+ <th>Method</th>
105
+ <th>Description</th>
106
+ </tr>
107
+ </thead>
108
+ <tbody>
109
+ <tr>
110
+ <td data-label="Method">
111
+ <p>resetEvents()</p>
112
+ </td>
113
+ <td data-label="Description">
114
+ <p>This method will reset the items and events</p>
115
+ </td>
116
+ </tr>
117
+ </tbody>
118
+ </table>
137
119
  <h3 id="events">Events</h3>
138
120
  <table>
139
121
  <thead>
@@ -43,7 +43,6 @@ if (sliderFade) {
43
43
  autoplay: 4000
44
44
  })
45
45
  sliderFade.addEventListener('slider:changed', (ev) => {
46
- console.log(ev)
47
46
  const src = mySliderObj._slides[ev.detail.previous].querySelector('img').getAttribute('src')
48
47
  sliderFade.style.backgroundImage = `url("${src}")`
49
48
  })
@@ -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.15
21
+ 0.1.17
22
22
  </span>
23
23
  </li>
24
24
  <li>
@@ -36,7 +36,7 @@ class DocLayout extends HTMLElement {
36
36
  </ul>
37
37
  </nav>
38
38
  </header>
39
- <aside id="sidebar" class="drawer" tabindex="0" hidden>
39
+ <aside id="sidebar" class="drawer" hidden>
40
40
  <header>
41
41
  <a href="/index.html">
42
42
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-rocket" viewBox="0 0 16 16">
package/js/_drawer.js CHANGED
@@ -45,7 +45,7 @@ export default class Drawer extends BaseComponent {
45
45
 
46
46
  this._isOpen = !this._element.hidden
47
47
 
48
- this._focus = this._element.querySelector('a,button') ?? null
48
+ this._focus = this._element.querySelector('[tabindex="0"]') ?? this._element.querySelector('a,button,input') ?? null
49
49
 
50
50
  this._cookie = this._options.cookie ? new Cookie(this._options.cookie) : null
51
51
 
@@ -73,7 +73,7 @@ export default class Drawer extends BaseComponent {
73
73
 
74
74
  // Window is smaller than breakpoint
75
75
  // -> Hide the drawer
76
- if (window.innerWidth < this._options.breakpoint) this.toggle(false)
76
+ if (window.innerWidth <= this._options.breakpoint) this.toggle(false)
77
77
 
78
78
  // On window resize
79
79
  // -> Toggle the drawer
@@ -85,7 +85,7 @@ export default class Drawer extends BaseComponent {
85
85
  if (window.innerWidth > this._options.breakpoint && (!this._isOpen && shouldBeOpen)) this.toggle(true)
86
86
 
87
87
  // Smaller than breakpoint -> Invisible
88
- if (window.innerWidth < this._options.breakpoint && this._isOpen) this.toggle(false)
88
+ if (window.innerWidth <= this._options.breakpoint && this._isOpen) this.toggle(false)
89
89
 
90
90
  }, 250)
91
91
  }
@@ -123,7 +123,12 @@ export default class Drawer extends BaseComponent {
123
123
  }
124
124
 
125
125
  // Add the focus if open
126
- if (this._focus && this._isOpen) this._focus.focus()
126
+ // * Need to wait the transition before make it focused
127
+ if (this._focus && this._isOpen) {
128
+ this._element.addEventListener("transitionend", () => {
129
+ this._focus.focus()
130
+ }, { once: true })
131
+ }
127
132
 
128
133
  }
129
134
 
package/js/_dropdown.js CHANGED
@@ -37,6 +37,7 @@ export default class Dropdown extends BaseComponent {
37
37
  // Define the properties
38
38
  this._button = this._element.querySelector('[aria-controls]')
39
39
  this._content = document.getElementById(this._button.getAttribute('aria-controls'))
40
+ this._focus = this._element.querySelector('[tabindex="0"]') ?? this._element.querySelector('a,button,input') ?? null
40
41
 
41
42
  // Init the event listener
42
43
  this.#init()
@@ -88,8 +89,13 @@ export default class Dropdown extends BaseComponent {
88
89
  // Change visibility of the content
89
90
  this._content.hidden = !value
90
91
 
91
- // Put the focus on the content
92
- if (value) this._content.focus()
92
+ // Add the focus if open
93
+ // * Need to wait the transition before make it focused
94
+ if (this._focus && value) {
95
+ this._element.addEventListener("transitionend", () => {
96
+ this._focus.focus()
97
+ }, { once: true })
98
+ }
93
99
 
94
100
  // Emmit event
95
101
  this.emmitEvent('changed', { isOpen: !this._content.hidden })
package/js/_sortable.js CHANGED
@@ -29,6 +29,13 @@ export default class Sortable extends BaseComponent {
29
29
  this._withHandle = this._element.querySelector('[data-handle=sortable]') ? true : false
30
30
  this._current = null
31
31
 
32
+ // Lier une seule fois les méthodes à `this`
33
+ this.handleMouseDown = this.handleMouseDown.bind(this)
34
+ this.handleMouseUp = this.handleMouseUp.bind(this)
35
+ this.drag = this.drag.bind(this)
36
+ this.dragging = this.dragging.bind(this)
37
+ this.drop = this.drop.bind(this)
38
+
32
39
  // Init the event listener
33
40
  this.#init()
34
41
 
@@ -44,41 +51,99 @@ export default class Sortable extends BaseComponent {
44
51
  // Prevent default animation at the drop
45
52
  this._element.addEventListener('dragover', (e) => e.preventDefault())
46
53
 
47
- // Events directly on the items
48
- this.items.forEach((item) => {
54
+ // Init the events on the items
55
+ this.#initEvents()
56
+
57
+ }
49
58
 
50
- // Toggle the [dragable] attribute
51
- item.addEventListener('mousedown', (e) => { if (!this._withHandle || (e.target.hasAttribute('data-handle') && e.target.getAttribute('data-handle') === 'sortable')) item.draggable = true })
52
- item.addEventListener('mouseup', () => item.draggable = false)
59
+ /**
60
+ * Get the list of the items
61
+ * This is used for the emmitEvent
62
+ *
63
+ * @return {object}
64
+ */
65
+ get _items() {
66
+ return this._element.querySelectorAll('[draggable]')
67
+ }
53
68
 
54
- // Drag and drop events
55
- item.addEventListener('dragstart', () => this.#drag(item))
56
- item.addEventListener('dragenter', () => this.#dragging(item))
57
- item.addEventListener('dragend', () => this.#drop(item))
58
69
 
59
- const btns = item.querySelectorAll('[data-go]')
60
- if (btns) btns.forEach(btn => btn.addEventListener('click', () => this.#move(item, btn.getAttribute('data-go') == 'up')))
70
+ /**
71
+ * Init the items and the event listeners
72
+ *
73
+ * @private
74
+ */
75
+ #initEvents() {
76
+
77
+ // Get the items
78
+ //this._items = this._element.querySelectorAll('[draggable]')
79
+
80
+ // Add the events
81
+ this._items.forEach(item => {
82
+ item.addEventListener('mousedown', this.handleMouseDown)
83
+ item.addEventListener('mouseup', this.handleMouseUp)
84
+ item.addEventListener('dragstart', this.drag)
85
+ item.addEventListener('dragenter', this.dragging)
86
+ item.addEventListener('dragend', this.drop)
87
+ })
88
+ }
61
89
 
90
+ /**
91
+ * Reset the event listeners
92
+ *
93
+ * @private
94
+ */
95
+ resetEvents() {
96
+
97
+ // Remove the listeners
98
+ this._items.forEach((item) => {
99
+ item.removeEventListener('mousedown', this.handleMouseDown)
100
+ item.removeEventListener('mouseup', this.handleMouseUp)
101
+ item.removeEventListener('dragstart', this.drag)
102
+ item.removeEventListener('dragenter', this.dragging)
103
+ item.removeEventListener('dragend', this.drop)
62
104
  })
63
105
 
106
+ // Re-initialise the items
107
+ this.#initEvents()
64
108
  }
65
109
 
66
110
  /**
67
- * Get the list of the items
111
+ * Handle the mousedown event
68
112
  *
69
- * @return {object}
113
+ * @private
70
114
  */
71
- get items() {
72
- return this._element.querySelectorAll('[draggable]')
115
+ handleMouseDown(e) {
116
+ // Avoid if not an element
117
+ if (!(e.target instanceof Element)) return
118
+ const target = e.target.closest('[draggable]')
119
+ if (!this._withHandle || (e.target.hasAttribute('data-handle') && e.target.getAttribute('data-handle') === 'sortable')) target.draggable = true
120
+ }
121
+
122
+ /**
123
+ * Handle the mouseup event
124
+ *
125
+ * @private
126
+ */
127
+ handleMouseUp(e) {
128
+ // Avoid if not an element
129
+ if (!(e.target instanceof Element)) return
130
+ const target = e.target.closest('[draggable]')
131
+ target.draggable = false
73
132
  }
74
133
 
75
134
  /**
76
135
  * Drag an item
77
136
  *
78
- * @param {HTMLElement} item - The current item
79
137
  * @private
80
138
  */
81
- #drag(item) {
139
+ drag(e) {
140
+
141
+ // Avoid if not an element
142
+ if (!(e.target instanceof Element)) return
143
+
144
+ // Get the item
145
+ // * Bug with event listeners reset if passing some data
146
+ const item = e.target.closest('[draggable]')
82
147
 
83
148
  // Check for errors
84
149
  if (!(item instanceof HTMLElement)) throw new Error(ErrorMessage.instanceOf('item', 'HTMLElement'))
@@ -93,17 +158,23 @@ export default class Sortable extends BaseComponent {
93
158
  item.setAttribute('aria-grabbed', true)
94
159
 
95
160
  // Run custom event
96
- this.emmitEvent('drag', { items: this.items, current: item })
161
+ this.emmitEvent('drag', { items: this._items, current: item })
97
162
 
98
163
  }
99
164
 
100
165
  /**
101
166
  * When dragging an item, move it before or after an element
102
167
  *
103
- * @param {HTMLElement} item - The current item
104
168
  * @private
105
169
  */
106
- #dragging(item) {
170
+ dragging(e) {
171
+
172
+ // Avoid if not an element
173
+ if (!(e.target instanceof Element)) return
174
+
175
+ // Get the item
176
+ // * Bug with event listeners reset if passing some data
177
+ const item = e.target.closest('[draggable]')
107
178
 
108
179
  // Check for errors
109
180
  if (!(item instanceof HTMLElement)) throw new Error(ErrorMessage.instanceOf('item', 'HTMLElement'))
@@ -120,10 +191,16 @@ export default class Sortable extends BaseComponent {
120
191
  /**
121
192
  * Drop an item
122
193
  *
123
- * @param {HTMLElement} item - The current item
124
194
  * @private
125
195
  */
126
- #drop(item) {
196
+ drop(e) {
197
+
198
+ // Avoid if not an element
199
+ if (!(e.target instanceof Element)) return
200
+
201
+ // Get the item
202
+ // * Bug with event listeners reset if passing some data
203
+ const item = e.target.closest('[draggable]')
127
204
 
128
205
  // Check for errors
129
206
  if (!(item instanceof HTMLElement)) throw new Error(ErrorMessage.instanceOf('item', 'HTMLElement'))
@@ -141,30 +218,8 @@ export default class Sortable extends BaseComponent {
141
218
  item.draggable = false
142
219
 
143
220
  // Run custom event
144
- this.emmitEvent('drop', { items: this.items, current: item })
221
+ this.emmitEvent('drop', { items: this._items, current: item })
145
222
 
146
223
  }
147
224
 
148
- /**
149
- * Manually move up and down
150
- *
151
- * @param {HTMLElement} item - The current item
152
- * @private
153
- */
154
- #move(item, goUp = false) {
155
-
156
- const sibling = goUp ? item.previousElementSibling : item.nextElementSibling
157
-
158
- if (sibling) {
159
- this._element.insertBefore(item, goUp ? sibling : sibling.nextElementSibling)
160
- } else if (!goUp) {
161
- this._element.appendChild(item)
162
- }
163
-
164
- // Run custom event
165
- this.emmitEvent('moved', { items: this.items, current: item })
166
-
167
- }
168
-
169
-
170
225
  }
@@ -102,7 +102,6 @@ describe('Structure of the class', () => {
102
102
  })
103
103
 
104
104
  test('Constructor: Return the correct properties', () => {
105
- console.log(document.querySelectorAll('#slider [role=tabpanel]') == fakeSlider._slides)
106
105
  expect(fakeSlider).toHaveProperty('_element')
107
106
  expect(fakeSlider).toHaveProperty('_options')
108
107
  expect(fakeSlider).toHaveProperty('_slides')
@@ -8,12 +8,10 @@
8
8
  * - Constructor: Return the correct properties
9
9
  * - Mousedown & Mouseup: Without handle toggle the [draggable] attribute
10
10
  * - Mousedown & Mouseup: With handle toggle the [draggable] attribute
11
- * - #Drag(): Add the [aria-grabbed] attribute
12
- * - #Drag(): Emmit the sortable:drag event
13
- * - #Drop(): Remove the [aria-grabbed] attribute
14
- * - #Drop(): Emmit the sortable:drop event
15
- * - #Move(): Go down on click and emmit the sortable:moved event
16
- * - #Move(): Go up on click and emmit the sortable:moved event
11
+ * - Drag(): Add the [aria-grabbed] attribute
12
+ * - Drag(): Emmit the sortable:drag event
13
+ * - Drop(): Remove the [aria-grabbed] attribute
14
+ * - Drop(): Emmit the sortable:drop event
17
15
  */
18
16
 
19
17
  import { describe, test, expect, beforeAll, vi } from "vitest"
@@ -31,9 +29,9 @@ beforeAll(() => {
31
29
 
32
30
  document.body.innerHTML =
33
31
  '<ul id="fakeList">' +
34
- '<li id="first" draggable="false"><button data-go="up">UP</button><button data-go="down">Down</button>One</li>' +
35
- '<li draggable="false"><button data-go="up">UP</button><button data-go="down">Down</button>Two</li>' +
36
- '<li draggable="false"><button data-go="up">UP</button><button data-go="down">Down</button>Three</li>' +
32
+ '<li id="first" draggable="false">One</li>' +
33
+ '<li draggable="false">Two</li>' +
34
+ '<li draggable="false">Three</li>' +
37
35
  '</ul>' +
38
36
  '<table id="fakeTable">' +
39
37
  '<tr draggable="false"><td data-handle="sortable">DRAG</td><td>One</td></tr>' +
@@ -54,8 +52,8 @@ describe('Structure of the class', () => {
54
52
  expect(fakeListSortable._withHandle).toBeTypeOf('boolean')
55
53
  expect(fakeListSortable._withHandle).toBe(false)
56
54
  expect(fakeTableSortable._withHandle).toBe(true)
57
- expect(fakeListSortable.items).toBeTypeOf('object')
58
- expect(fakeListSortable.items).toStrictEqual(document.querySelectorAll('#fakeList li'))
55
+ expect(fakeListSortable._items).toBeTypeOf('object')
56
+ expect(fakeListSortable._items).toStrictEqual(document.querySelectorAll('#fakeList li'))
59
57
  })
60
58
 
61
59
  })
@@ -86,7 +84,7 @@ describe('Mousedown & Mouseup', () => {
86
84
 
87
85
  })
88
86
 
89
- describe('#Drag()', () => {
87
+ describe('Drag()', () => {
90
88
 
91
89
  test('Add the [aria-grabbed] attribute', () => {
92
90
  expect(fakeListItem.hasAttribute('aria-grabbed')).toBeFalsy()
@@ -103,12 +101,12 @@ describe('#Drag()', () => {
103
101
  expect(eventSpy).not.toHaveBeenCalled()
104
102
  fireEvent(fakeListItem, new MouseEvent('mousedown'))
105
103
  fireEvent(fakeListItem, new MouseEvent('dragstart'))
106
- expect(eventSpy).toHaveBeenCalledWith('drag', { current: fakeListItem, items: fakeListSortable.items })
104
+ expect(eventSpy).toHaveBeenCalledWith('drag', { current: fakeListItem, items: fakeListSortable._items })
107
105
  })
108
106
 
109
107
  })
110
108
 
111
- describe('#Drop()', () => {
109
+ describe('Drop()', () => {
112
110
 
113
111
  test('Remove the [aria-grabbed] attribute', () => {
114
112
  expect(fakeListItem.hasAttribute('aria-grabbed')).toBeTruthy()
@@ -121,26 +119,7 @@ describe('#Drop()', () => {
121
119
  fireEvent(fakeListItem, new MouseEvent('mousedown')) // First drag item
122
120
  fireEvent(fakeListItem, new MouseEvent('dragstart')) // First drag item
123
121
  fireEvent(fakeListItem, new MouseEvent('dragend'))
124
- expect(eventSpy).toHaveBeenCalledWith('drop', { current: fakeListItem, items: fakeListSortable.items })
125
- })
126
-
127
- })
128
-
129
- describe('#Move()', () => {
130
-
131
- test('Go down on click and emmit the sortable:moved event', () => {
132
- const eventSpy = vi.spyOn(fakeListSortable, 'emmitEvent')
133
- fireEvent(fakeListItem.querySelector('[data-go=down]'), new MouseEvent('click'))
134
- expect(fakeListItem).toBe(document.getElementById('fakeList').children[1])
135
- expect(eventSpy).toHaveBeenCalledWith('moved', { current: fakeListItem, items: fakeListSortable.items })
136
- })
137
-
138
- test('Go up on click and emmit the sortable:moved event', () => {
139
- const eventSpy = vi.spyOn(fakeListSortable, 'emmitEvent')
140
- expect(fakeListItem).toBe(document.getElementById('fakeList').children[1])
141
- fireEvent(fakeListItem.querySelector('[data-go=up]'), new MouseEvent('click'))
142
- expect(fakeListItem).toBe(document.getElementById('fakeList').children[0])
143
- expect(eventSpy).toHaveBeenCalledWith('moved', { current: fakeListItem, items: fakeListSortable.items })
122
+ expect(eventSpy).toHaveBeenCalledWith('drop', { current: fakeListItem, items: fakeListSortable._items })
144
123
  })
145
124
 
146
125
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@natachah/vanilla-frontend",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "A vanilla frontend framework",
5
5
  "keywords": [
6
6
  "html5",