@natachah/vanilla-frontend 0.1.10 → 0.1.12
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/pages/components/drawer.html +43 -2
- package/docs/pages/components/list.html +4 -3
- package/docs/pages/javascript/sortable.html +37 -0
- package/docs/src/js/doc-layout.js +1 -1
- package/js/_drawer.js +30 -8
- package/js/_sortable.js +27 -2
- package/js/tests/sortable.test.js +25 -4
- package/natachah-vanilla-frontend-0.1.12.tgz +0 -0
- package/package.json +1 -1
- package/scss/abstracts/_mixins.scss +1 -1
- package/natachah-vanilla-frontend-0.1.10.tgz +0 -0
|
@@ -65,8 +65,49 @@
|
|
|
65
65
|
|
|
66
66
|
<h2>Javascript</h2>
|
|
67
67
|
<p>This component is mostly in javascript, to use it you must import the javascript file and create a new Drawer object.</p>
|
|
68
|
-
<p>You can
|
|
69
|
-
|
|
68
|
+
<p>You can have a <b>Backdrop</b> if you want to make it more like a drawer opening on the front of the content, you juste need a <code>#backdrop</code> somewhere on your page.</p>
|
|
69
|
+
|
|
70
|
+
<h3>Options</h3>
|
|
71
|
+
|
|
72
|
+
<table>
|
|
73
|
+
<thead>
|
|
74
|
+
<tr>
|
|
75
|
+
<th>Name</th>
|
|
76
|
+
<th>Description</th>
|
|
77
|
+
<th>Value</th>
|
|
78
|
+
</tr>
|
|
79
|
+
</thead>
|
|
80
|
+
<tbody>
|
|
81
|
+
<tr>
|
|
82
|
+
<td data-label="Name">
|
|
83
|
+
<p>breakpoint</p>
|
|
84
|
+
</td>
|
|
85
|
+
<td data-label="Description">
|
|
86
|
+
<p>The breakpoint to open/close the drawer</p>
|
|
87
|
+
</td>
|
|
88
|
+
<td data-label="Value">
|
|
89
|
+
<p><code>960</code> as an <code>int</code></p>
|
|
90
|
+
</td>
|
|
91
|
+
</tr>
|
|
92
|
+
<tr>
|
|
93
|
+
<td data-label="Name">
|
|
94
|
+
<p>cookie</p>
|
|
95
|
+
</td>
|
|
96
|
+
<td data-label="Description">
|
|
97
|
+
<p>The cookie name to save if you want to keep it open/close on refresh</p>
|
|
98
|
+
</td>
|
|
99
|
+
<td data-label="Value">
|
|
100
|
+
<p><code>false</code> by default, or a <code>string</code></p>
|
|
101
|
+
</td>
|
|
102
|
+
</tr>
|
|
103
|
+
</tbody>
|
|
104
|
+
</table>
|
|
105
|
+
|
|
106
|
+
<doc-code data-type="js">
|
|
107
|
+
import Drawer from '@natachah/vanilla-frontend/js/utilities/_drawer.js'
|
|
108
|
+
const drawer = document.getElementById('drawer')
|
|
109
|
+
if (drawer) new Drawer(drawer, { breakpoint : 960, cookkie: '_drawer-cookie' })
|
|
110
|
+
</doc-code>
|
|
70
111
|
|
|
71
112
|
<blockquote>
|
|
72
113
|
<p>Main use case are sidebar menu or main navigation menu.</p>
|
|
@@ -62,7 +62,8 @@
|
|
|
62
62
|
<li><button disabled>List B (button disabled)</button></li>
|
|
63
63
|
<li>List C</li>
|
|
64
64
|
<li><a role="button" href="#">List D (link)</a></li>
|
|
65
|
-
<li><a role="button">
|
|
65
|
+
<li><span>List E</span><a role="button" href="#">Not only child (link)</a></li>
|
|
66
|
+
<li><a role="button">List F (link disabled)</a></li>
|
|
66
67
|
</ul>
|
|
67
68
|
</doc-demo>
|
|
68
69
|
|
|
@@ -126,7 +127,7 @@
|
|
|
126
127
|
</doc-code>
|
|
127
128
|
<doc-code id="scss" data-type="scss" role="tabpanel">
|
|
128
129
|
$outline-variations: (
|
|
129
|
-
|
|
130
|
+
list
|
|
130
131
|
);
|
|
131
132
|
</doc-code>
|
|
132
133
|
</div>
|
|
@@ -161,7 +162,7 @@
|
|
|
161
162
|
</doc-code>
|
|
162
163
|
<doc-code id="scss" data-type="scss" role="tabpanel">
|
|
163
164
|
$color-variations: (
|
|
164
|
-
|
|
165
|
+
list: (primary)
|
|
165
166
|
);
|
|
166
167
|
</doc-code>
|
|
167
168
|
</div>
|
|
@@ -95,6 +95,43 @@
|
|
|
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
|
+
|
|
98
135
|
<h2 id="javascript">Javascript</h2>
|
|
99
136
|
<p>To enable this component you need to import the javascript file and create a new Sortable object.</p>
|
|
100
137
|
<h3 id="events">Events</h3>
|
|
@@ -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.
|
|
21
|
+
0.1.12
|
|
22
22
|
</span>
|
|
23
23
|
</li>
|
|
24
24
|
<li>
|
package/js/_drawer.js
CHANGED
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
|
|
13
13
|
import BaseComponent from './utilities/_base-component'
|
|
14
14
|
import ErrorMessage from "./utilities/_error"
|
|
15
|
+
import Cookie from "./utilities/_cookie"
|
|
15
16
|
|
|
16
17
|
export default class Drawer extends BaseComponent {
|
|
17
18
|
|
|
18
19
|
static OPTIONS = {
|
|
19
20
|
breakpoint: 960,
|
|
21
|
+
cookie: false
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
/**
|
|
@@ -44,6 +46,8 @@ export default class Drawer extends BaseComponent {
|
|
|
44
46
|
|
|
45
47
|
this._focus = this._element.querySelector('a,button') ?? null
|
|
46
48
|
|
|
49
|
+
this._cookie = this._options.cookie ? new Cookie(this._options.cookie) : null
|
|
50
|
+
|
|
47
51
|
// Init the event listener
|
|
48
52
|
this.#init()
|
|
49
53
|
|
|
@@ -56,30 +60,50 @@ export default class Drawer extends BaseComponent {
|
|
|
56
60
|
*/
|
|
57
61
|
#init() {
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
const isOpenValue = window.innerWidth > this._options.breakpoint && !this._isOpen
|
|
64
|
+
|
|
65
|
+
// Init the default cookie
|
|
66
|
+
if (this._cookie && !this._cookie.has('open')) this._cookie.set({ 'open': isOpenValue })
|
|
67
|
+
|
|
68
|
+
// Init the default open or close
|
|
69
|
+
if (!this._cookie || (this._cookie.get('open') && !this._isOpen)) this.toggle()
|
|
61
70
|
|
|
62
71
|
// On resize check if need to open/close the drawer
|
|
63
72
|
window.onresize = () => {
|
|
64
73
|
clearTimeout(this._timeout)
|
|
65
74
|
this._timeout = setTimeout(() => {
|
|
66
|
-
if ((window.innerWidth
|
|
75
|
+
if ((window.innerWidth > this._options.breakpoint && !this._isOpen) || (window.innerWidth < this._options.breakpoint && this._isOpen)) {
|
|
76
|
+
this.toggle()
|
|
77
|
+
this.#resetCookie()
|
|
78
|
+
}
|
|
67
79
|
}, 250)
|
|
68
80
|
}
|
|
69
81
|
|
|
70
82
|
// On click on the button toggle the drawer
|
|
71
|
-
this._buttons.forEach((button) => button.addEventListener('click', () =>
|
|
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
|
+
}))
|
|
72
88
|
|
|
73
89
|
// On click on the backdrop, close the drawer
|
|
74
90
|
if (this._backdrop) this._backdrop.addEventListener('click', () => this.toggle())
|
|
75
91
|
|
|
76
92
|
}
|
|
77
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Reset the cookie
|
|
96
|
+
*
|
|
97
|
+
*/
|
|
98
|
+
#resetCookie() {
|
|
99
|
+
if (this._cookie) this._cookie.set({ 'open': this._isOpen })
|
|
100
|
+
}
|
|
101
|
+
|
|
78
102
|
/**
|
|
79
103
|
* Toggle the drawer
|
|
80
104
|
*
|
|
81
105
|
*/
|
|
82
|
-
toggle(
|
|
106
|
+
toggle() {
|
|
83
107
|
|
|
84
108
|
// Change the state
|
|
85
109
|
this._isOpen = !this._isOpen
|
|
@@ -93,9 +117,7 @@ export default class Drawer extends BaseComponent {
|
|
|
93
117
|
// Change the [hidden] attribute on the drawer
|
|
94
118
|
this._element.hidden = !this._isOpen
|
|
95
119
|
|
|
96
|
-
// Toggle the focus
|
|
97
|
-
if (enableFocus && this._focus && this._isOpen) this._focus.focus()
|
|
98
|
-
|
|
99
120
|
}
|
|
100
121
|
|
|
122
|
+
|
|
101
123
|
}
|
package/js/_sortable.js
CHANGED
|
@@ -53,9 +53,12 @@ export default class Sortable extends BaseComponent {
|
|
|
53
53
|
|
|
54
54
|
// Drag and drop events
|
|
55
55
|
item.addEventListener('dragstart', () => this.#drag(item))
|
|
56
|
-
item.addEventListener('dragenter', () => this.#
|
|
56
|
+
item.addEventListener('dragenter', () => this.#dragging(item))
|
|
57
57
|
item.addEventListener('dragend', () => this.#drop(item))
|
|
58
58
|
|
|
59
|
+
const btns = item.querySelectorAll('[data-go]')
|
|
60
|
+
if (btns) btns.forEach(btn => btn.addEventListener('click', () => this.#move(item, btn.getAttribute('data-go') == 'up')))
|
|
61
|
+
|
|
59
62
|
})
|
|
60
63
|
|
|
61
64
|
}
|
|
@@ -100,7 +103,7 @@ export default class Sortable extends BaseComponent {
|
|
|
100
103
|
* @param {HTMLElement} item - The current item
|
|
101
104
|
* @private
|
|
102
105
|
*/
|
|
103
|
-
#
|
|
106
|
+
#dragging(item) {
|
|
104
107
|
|
|
105
108
|
// Check for errors
|
|
106
109
|
if (!(item instanceof HTMLElement)) throw new Error(ErrorMessage.instanceOf('item', 'HTMLElement'))
|
|
@@ -142,4 +145,26 @@ export default class Sortable extends BaseComponent {
|
|
|
142
145
|
|
|
143
146
|
}
|
|
144
147
|
|
|
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
|
+
|
|
145
170
|
}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* - #Drag(): Emmit the sortable:drag event
|
|
13
13
|
* - #Drop(): Remove the [aria-grabbed] attribute
|
|
14
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
|
|
15
17
|
*/
|
|
16
18
|
|
|
17
19
|
import { describe, test, expect, beforeAll, vi } from "vitest"
|
|
@@ -29,9 +31,9 @@ beforeAll(() => {
|
|
|
29
31
|
|
|
30
32
|
document.body.innerHTML =
|
|
31
33
|
'<ul id="fakeList">' +
|
|
32
|
-
'<li draggable="false">One</li>' +
|
|
33
|
-
'<li draggable="false">Two</li>' +
|
|
34
|
-
'<li draggable="false">Three</li>' +
|
|
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>' +
|
|
35
37
|
'</ul>' +
|
|
36
38
|
'<table id="fakeTable">' +
|
|
37
39
|
'<tr draggable="false"><td data-handle="sortable">DRAG</td><td>One</td></tr>' +
|
|
@@ -41,7 +43,7 @@ beforeAll(() => {
|
|
|
41
43
|
|
|
42
44
|
fakeListSortable = new Sortable(document.getElementById('fakeList'))
|
|
43
45
|
fakeTableSortable = new Sortable(document.getElementById('fakeTable'))
|
|
44
|
-
fakeListItem = document.
|
|
46
|
+
fakeListItem = document.getElementById('first')
|
|
45
47
|
|
|
46
48
|
})
|
|
47
49
|
|
|
@@ -122,4 +124,23 @@ describe('#Drop()', () => {
|
|
|
122
124
|
expect(eventSpy).toHaveBeenCalledWith('drop', { current: fakeListItem, items: fakeListSortable.items })
|
|
123
125
|
})
|
|
124
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 })
|
|
144
|
+
})
|
|
145
|
+
|
|
125
146
|
})
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
margin: 0;
|
|
130
130
|
text-align: var(--list-text-align, left);
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
& > *:is(a[role=button]:only-child, button:only-child) {
|
|
133
133
|
display: block;
|
|
134
134
|
width: 100%;
|
|
135
135
|
text-align: var(--list-text-align, left);
|
|
Binary file
|