@natachah/vanilla-frontend 0.1.16 → 0.1.18

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.
@@ -198,7 +198,25 @@
198
198
 
199
199
  <h2>Javascript</h2>
200
200
  <p>To enable this component you need to import the javascript file and create a new Tree object.</p>
201
-
201
+ <h3>Methods</h3>
202
+ <table>
203
+ <thead>
204
+ <tr>
205
+ <th>Method</th>
206
+ <th>Description</th>
207
+ </tr>
208
+ </thead>
209
+ <tbody>
210
+ <tr>
211
+ <td data-label="Method">
212
+ <p>resetEvents()</p>
213
+ </td>
214
+ <td data-label="Description">
215
+ <p>This method will reset the items and events</p>
216
+ </td>
217
+ </tr>
218
+ </tbody>
219
+ </table>
202
220
  <h3>Events</h3>
203
221
  <table>
204
222
  <thead>
@@ -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.16
21
+ 0.1.18
22
22
  </span>
23
23
  </li>
24
24
  <li>
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('[tabindex="0"]') ?? this._element.querySelector('a,button,input') ?? null
48
+ this._focus = this._element.getAttribute('tabindex') === '0' ? this._element : this._element.querySelector('[tabindex="0"]') ?? this._element.querySelector('button, a, input')
49
49
 
50
50
  this._cookie = this._options.cookie ? new Cookie(this._options.cookie) : null
51
51
 
package/js/_dropdown.js CHANGED
@@ -37,7 +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
+ this._focus = this._content.getAttribute('tabindex') === '0' ? this._content : this._content.querySelector('[tabindex="0"]') ?? this._content.querySelector('button, a, input')
41
41
 
42
42
  // Init the event listener
43
43
  this.#init()
package/js/_sortable.js CHANGED
@@ -26,11 +26,11 @@ export default class Sortable extends BaseComponent {
26
26
  super(el, options, 'sortable')
27
27
 
28
28
  // Define the properties
29
- this._items = null
30
29
  this._withHandle = this._element.querySelector('[data-handle=sortable]') ? true : false
31
30
  this._current = null
32
31
 
33
- // Lier une seule fois les méthodes à `this`
32
+ // Bind this only one time foreach methods
33
+ // * Because I add and remove events
34
34
  this.handleMouseDown = this.handleMouseDown.bind(this)
35
35
  this.handleMouseUp = this.handleMouseUp.bind(this)
36
36
  this.drag = this.drag.bind(this)
@@ -57,6 +57,17 @@ export default class Sortable extends BaseComponent {
57
57
 
58
58
  }
59
59
 
60
+ /**
61
+ * Get the list of the items
62
+ * This is used for the emmitEvent
63
+ *
64
+ * @return {object}
65
+ */
66
+ get _items() {
67
+ return this._element.querySelectorAll('[draggable]')
68
+ }
69
+
70
+
60
71
  /**
61
72
  * Init the items and the event listeners
62
73
  *
@@ -64,9 +75,6 @@ export default class Sortable extends BaseComponent {
64
75
  */
65
76
  #initEvents() {
66
77
 
67
- // Get the items
68
- this._items = this._element.querySelectorAll('[draggable]')
69
-
70
78
  // Add the events
71
79
  this._items.forEach(item => {
72
80
  item.addEventListener('mousedown', this.handleMouseDown)
@@ -148,7 +156,7 @@ export default class Sortable extends BaseComponent {
148
156
  item.setAttribute('aria-grabbed', true)
149
157
 
150
158
  // Run custom event
151
- this.emmitEvent('drag', { items: this.items, current: item })
159
+ this.emmitEvent('drag', { items: this._items, current: item })
152
160
 
153
161
  }
154
162
 
@@ -208,7 +216,7 @@ export default class Sortable extends BaseComponent {
208
216
  item.draggable = false
209
217
 
210
218
  // Run custom event
211
- this.emmitEvent('drop', { items: this.items, current: item })
219
+ this.emmitEvent('drop', { items: this._items, current: item })
212
220
 
213
221
  }
214
222
 
package/js/_toggle.js CHANGED
@@ -103,7 +103,10 @@ export default class Toggle extends BaseComponent {
103
103
  // Toggle the [hidden] attribute
104
104
  toggable.hidden = this.value !== toggleValue && groupValue !== toggleValue
105
105
 
106
- if (!toggable.hidden && toggable.hasAttribute('tabindex')) toggable.focus()
106
+ if (!toggable.hidden) {
107
+ const focus = toggable.getAttribute('tabindex') === '0' ? toggable : toggable.querySelector('[tabindex="0"]') ?? toggable.querySelector('button, a, input')
108
+ if (focus) focus.focus()
109
+ }
107
110
 
108
111
  })
109
112
 
package/js/_tree.js CHANGED
@@ -29,7 +29,9 @@ export default class Tree extends BaseComponent {
29
29
 
30
30
  this._withHandle = this._type == 'grid' && this._element.querySelector('[data-handle=tree]') ? true : false
31
31
 
32
- this._items = this._element.querySelectorAll('[aria-expanded]')
32
+ // Bind this only one time foreach methods
33
+ // * Because I add and remove events
34
+ this.toggle = this.toggle.bind(this)
33
35
 
34
36
  // Init the event listener
35
37
  this.#init()
@@ -43,12 +45,45 @@ export default class Tree extends BaseComponent {
43
45
  */
44
46
  #init() {
45
47
 
46
- this._items.forEach(item => item.addEventListener('click', (e) => {
47
- if (!this._withHandle || (e.target.hasAttribute('data-handle') && e.target.getAttribute('data-handle') === 'tree')) {
48
- e.stopPropagation()
49
- this.toggle(item)
50
- }
51
- }))
48
+ // Init the events on the items
49
+ this.#initEvents()
50
+
51
+ }
52
+
53
+ /**
54
+ * Get the list of the items
55
+ *
56
+ * @return {object}
57
+ */
58
+ get _items() {
59
+ return this._element.querySelectorAll('[aria-expanded]')
60
+ }
61
+
62
+ /**
63
+ * Init the items and the event listeners
64
+ *
65
+ * @private
66
+ */
67
+ #initEvents() {
68
+ this._items.forEach(item => {
69
+ item.addEventListener('click', this.toggle)
70
+ })
71
+ }
72
+
73
+ /**
74
+ * Reset the event listeners
75
+ *
76
+ * @private
77
+ */
78
+ resetEvents() {
79
+
80
+ // Remove the listeners
81
+ this._items.forEach((item) => {
82
+ item.removeEventListener('click', this.toggle)
83
+ })
84
+
85
+ // Re-initialise the items
86
+ this.#initEvents()
52
87
 
53
88
  }
54
89
 
@@ -57,7 +92,21 @@ export default class Tree extends BaseComponent {
57
92
  *
58
93
  * @param {HTMLElement} item - The current item
59
94
  */
60
- toggle(item) {
95
+ toggle(e) {
96
+
97
+ let item
98
+
99
+ if (e instanceof Event) {
100
+ // If it's an event verify about the handle + if target is an HTML element
101
+ if (!(e.target instanceof Element)) return
102
+ if (this._withHandle && (!e.target.hasAttribute('data-handle') || e.target.getAttribute('data-handle') !== 'tree')) return
103
+ e.stopPropagation()
104
+ item = e.target.closest('[aria-expanded]')
105
+ } else {
106
+ // If it's NOT an event verify that it's an HTML element
107
+ if (!(e instanceof Element)) return
108
+ item = e
109
+ }
61
110
 
62
111
  // Check for errors
63
112
  if (!(item instanceof HTMLElement)) throw new Error(ErrorMessage.instanceOf('item', 'HTMLElement'))
@@ -74,8 +123,36 @@ export default class Tree extends BaseComponent {
74
123
 
75
124
  // Set the focus on the required child
76
125
  if (!isExpanded) {
77
- const childToFocus = children.find(el => el.hasAttribute('tabindex')) ?? null
78
- if (childToFocus) childToFocus.focus()
126
+
127
+ let childToFocus = null
128
+
129
+ const child = children.find(el => {
130
+
131
+ // Check if the child have a tabindex
132
+ if (el.getAttribute('tabindex') === '0') {
133
+ childToFocus = el
134
+ return el
135
+ }
136
+
137
+ // Otherwise if an element inside the child have the tabindex
138
+ const childWithTabIndex = el.querySelector('[tabindex="0"]')
139
+ if (childWithTabIndex) {
140
+ childToFocus = childWithTabIndex
141
+ return childWithTabIndex
142
+ }
143
+
144
+ // Otherwise get the first focusable element
145
+ childToFocus = el.querySelector('button, a, input')
146
+ return el
147
+
148
+ })
149
+
150
+ // Add the focus if open
151
+ // * Need to wait the transition before make it focused
152
+ if (child && childToFocus) {
153
+ childToFocus.focus()
154
+ }
155
+
79
156
  }
80
157
 
81
158
  // If type grid, collapse the subchildren
@@ -26,7 +26,7 @@ beforeAll(() => {
26
26
  document.body.innerHTML =
27
27
  '<div id="backdrop"></div>' +
28
28
  '<button aria-expanded="false" aria-pressed="false" aria-controls="drawer"></button>' +
29
- '<aside id="drawer" tabindex="0" hidden><button id="focus"></button></aside>'
29
+ '<aside id="drawer" hidden><button id="focus"></button></aside>'
30
30
 
31
31
  Object.defineProperty(window, 'innerWidth', { configurable: true, value: 1200 })
32
32
 
@@ -29,9 +29,9 @@ beforeAll(() => {
29
29
 
30
30
  document.body.innerHTML =
31
31
  '<ul id="fakeList">' +
32
- '<li id="first" draggable="false"><button data-go="up">UP</button><button data-go="down">Down</button>One</li>' +
33
- '<li draggable="false"><button data-go="up">UP</button><button data-go="down">Down</button>Two</li>' +
34
- '<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>' +
35
35
  '</ul>' +
36
36
  '<table id="fakeTable">' +
37
37
  '<tr draggable="false"><td data-handle="sortable">DRAG</td><td>One</td></tr>' +
@@ -101,7 +101,7 @@ describe('Drag()', () => {
101
101
  expect(eventSpy).not.toHaveBeenCalled()
102
102
  fireEvent(fakeListItem, new MouseEvent('mousedown'))
103
103
  fireEvent(fakeListItem, new MouseEvent('dragstart'))
104
- expect(eventSpy).toHaveBeenCalledWith('drag', { current: fakeListItem, items: fakeListSortable.items })
104
+ expect(eventSpy).toHaveBeenCalledWith('drag', { current: fakeListItem, items: fakeListSortable._items })
105
105
  })
106
106
 
107
107
  })
@@ -119,7 +119,7 @@ describe('Drop()', () => {
119
119
  fireEvent(fakeListItem, new MouseEvent('mousedown')) // First drag item
120
120
  fireEvent(fakeListItem, new MouseEvent('dragstart')) // First drag item
121
121
  fireEvent(fakeListItem, new MouseEvent('dragend'))
122
- expect(eventSpy).toHaveBeenCalledWith('drop', { current: fakeListItem, items: fakeListSortable.items })
122
+ expect(eventSpy).toHaveBeenCalledWith('drop', { current: fakeListItem, items: fakeListSortable._items })
123
123
  })
124
124
 
125
125
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@natachah/vanilla-frontend",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "A vanilla frontend framework",
5
5
  "keywords": [
6
6
  "html5",