@lemonadejs/tabs 2.2.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +13 -5
- package/dist/index.js +173 -71
- package/dist/style.css +30 -14
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -7,14 +7,18 @@ declare function Tabs(el: HTMLElement, options?: Tabs.Options): Tabs.Instance;
|
|
|
7
7
|
|
|
8
8
|
declare namespace Tabs {
|
|
9
9
|
|
|
10
|
-
interface
|
|
10
|
+
interface Item {
|
|
11
|
+
// Reference to an external DOM
|
|
12
|
+
el: HTMLElement,
|
|
13
|
+
// Tab header
|
|
11
14
|
title: string,
|
|
15
|
+
// HTML template
|
|
12
16
|
content: string,
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
interface Options {
|
|
16
20
|
/** Programmatically content */
|
|
17
|
-
data?:
|
|
21
|
+
data?: Item[];
|
|
18
22
|
/** Selected tab */
|
|
19
23
|
selected?: number;
|
|
20
24
|
/** Tabs position */
|
|
@@ -22,12 +26,16 @@ declare namespace Tabs {
|
|
|
22
26
|
/** Activate round borders */
|
|
23
27
|
round?: boolean;
|
|
24
28
|
/** On open event */
|
|
25
|
-
onopen?: (index: number) => void;
|
|
29
|
+
onopen?: (instance: object, index: number) => void;
|
|
30
|
+
/** Allow to create new tab button */
|
|
31
|
+
allowCreate?: boolean;
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
interface Instance {
|
|
35
|
+
/** Create a new option */
|
|
36
|
+
create: (item: Item, position?: number, select?: boolean) => void;
|
|
29
37
|
/** Programmatically content */
|
|
30
|
-
data
|
|
38
|
+
data: Item[];
|
|
31
39
|
/** Selected tab */
|
|
32
40
|
selected: number;
|
|
33
41
|
/** Tabs position */
|
|
@@ -35,7 +43,7 @@ declare namespace Tabs {
|
|
|
35
43
|
/** Activate round borders */
|
|
36
44
|
round?: boolean;
|
|
37
45
|
/** On open event */
|
|
38
|
-
onopen?: (index: number) => void;
|
|
46
|
+
onopen?: (instance: object, index: number) => void;
|
|
39
47
|
}
|
|
40
48
|
}
|
|
41
49
|
|
package/dist/index.js
CHANGED
|
@@ -17,76 +17,150 @@ if (! lemonade && typeof (require) === 'function') {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
const
|
|
20
|
+
const extract = function(root, self) {
|
|
21
|
+
if (! Array.isArray(self.data)) {
|
|
22
|
+
self.data = [];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (root.tagName) {
|
|
26
|
+
for (let i = 0; i < root.children.length; i++) {
|
|
27
|
+
self.data.push({
|
|
28
|
+
el: root.children[i],
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
} else {
|
|
32
|
+
root.forEach((child) => {
|
|
33
|
+
self.data.push({
|
|
34
|
+
el: child.element,
|
|
35
|
+
})
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const Tabs = function(children) {
|
|
21
41
|
let self = this
|
|
22
|
-
let elements = [];
|
|
23
42
|
|
|
43
|
+
// Add new tab
|
|
44
|
+
let createButton;
|
|
45
|
+
|
|
46
|
+
// Get the references from the root web component
|
|
47
|
+
let root;
|
|
48
|
+
let template = '';
|
|
24
49
|
if (this.tagName) {
|
|
25
|
-
|
|
26
|
-
|
|
50
|
+
root = this;
|
|
51
|
+
} else {
|
|
52
|
+
// References from LemonadeJS
|
|
53
|
+
if (typeof(children) === 'string') {
|
|
54
|
+
// Version 4
|
|
55
|
+
template = children;
|
|
56
|
+
} else if (children && children.length) {
|
|
57
|
+
// Version 5
|
|
58
|
+
root = children;
|
|
59
|
+
}
|
|
27
60
|
}
|
|
28
61
|
|
|
62
|
+
if (root) {
|
|
63
|
+
extract(root, self);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Process the data
|
|
29
67
|
if (self.data) {
|
|
30
68
|
for (let i = 0; i < self.data.length; i++) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
69
|
+
if (! self.data[i].el) {
|
|
70
|
+
// Create element
|
|
71
|
+
self.data[i].el = document.createElement('div');
|
|
72
|
+
// Create from content
|
|
73
|
+
if (self.data[i].content) {
|
|
74
|
+
self.data[i].el.innerHTML = self.data[i].content;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
35
77
|
}
|
|
36
78
|
}
|
|
37
79
|
|
|
38
|
-
if (! html) {
|
|
39
|
-
html = '';
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
self.tabs = [];
|
|
43
|
-
|
|
44
80
|
const select = function (index) {
|
|
81
|
+
// Make sure the index is a number
|
|
45
82
|
index = parseInt(index);
|
|
46
|
-
|
|
47
83
|
// Do not select tabs that does not exist
|
|
48
|
-
if (index >= 0 && index < self.
|
|
49
|
-
for (let i = 0; i < self.
|
|
84
|
+
if (index >= 0 && index < self.data.length) {
|
|
85
|
+
for (let i = 0; i < self.root.children.length; i++) {
|
|
50
86
|
self.headers.children[i].classList.remove('selected');
|
|
51
|
-
self.
|
|
87
|
+
self.root.children[i].classList.remove('selected');
|
|
52
88
|
}
|
|
53
89
|
self.headers.children[index].classList.add('selected');
|
|
54
|
-
self.
|
|
90
|
+
self.root.children[index].classList.add('selected');
|
|
55
91
|
}
|
|
56
92
|
}
|
|
57
93
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
94
|
+
const init = function(selected) {
|
|
95
|
+
let tabs = [];
|
|
96
|
+
for (let i = 0; i < self.data.length; i++) {
|
|
97
|
+
// Extract meta information from the DOM
|
|
98
|
+
if (! self.data[i].title) {
|
|
99
|
+
let ret = self.data[i].el.getAttribute('title');
|
|
100
|
+
if (ret != null) {
|
|
101
|
+
self.data[i].title = ret;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (! self.data[i].selected) {
|
|
105
|
+
let ret = self.data[i].el.getAttribute('selected');
|
|
106
|
+
if (ret != null) {
|
|
107
|
+
self.data[i].selected = ret;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
// Create tabs object
|
|
111
|
+
tabs[i] = {
|
|
112
|
+
title: self.data[i].title,
|
|
113
|
+
}
|
|
114
|
+
// Which one is selected by default
|
|
115
|
+
if (self.data[i].selected) {
|
|
116
|
+
selected = i;
|
|
117
|
+
}
|
|
61
118
|
|
|
62
|
-
|
|
63
|
-
self.tabs.push({ title: self.content.children[i].title });
|
|
119
|
+
self.root.appendChild(self.data[i].el)
|
|
64
120
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (
|
|
69
|
-
|
|
121
|
+
// Create headers
|
|
122
|
+
self.tabs = tabs;
|
|
123
|
+
// Default selected
|
|
124
|
+
if (typeof(selected) !== 'undefined') {
|
|
125
|
+
self.selected = selected;
|
|
126
|
+
}
|
|
127
|
+
// Add create new tab button
|
|
128
|
+
if (createButton) {
|
|
129
|
+
self.headers.appendChild(createButton);
|
|
70
130
|
}
|
|
71
|
-
select(index);
|
|
72
131
|
}
|
|
73
132
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
select(self.selected);
|
|
78
|
-
|
|
79
|
-
Dispatch.call(self, 'onopen', self, self.selected);
|
|
133
|
+
self.onload = function () {
|
|
134
|
+
if (template) {
|
|
135
|
+
extract(self.root, self);
|
|
80
136
|
}
|
|
137
|
+
|
|
138
|
+
init(self.selected || 0);
|
|
81
139
|
}
|
|
82
140
|
|
|
83
|
-
self.keydown = function(e) {
|
|
141
|
+
self.keydown = function(e, s) {
|
|
142
|
+
let index = null;
|
|
84
143
|
if (e.key === 'Enter') {
|
|
85
|
-
self.click(e);
|
|
144
|
+
self.click(e, s);
|
|
145
|
+
} else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
|
|
146
|
+
index = self.selected - 1;
|
|
147
|
+
if (index < 0) {
|
|
148
|
+
index = 0;
|
|
149
|
+
}
|
|
150
|
+
} else if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
|
|
151
|
+
index = self.selected + 1;
|
|
152
|
+
if (index > self.tabs.length-1) {
|
|
153
|
+
index = self.tabs.length-1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Make selection
|
|
158
|
+
if (index !== null) {
|
|
159
|
+
self.tabs[index].el.focus();
|
|
86
160
|
}
|
|
87
161
|
}
|
|
88
162
|
|
|
89
|
-
self.
|
|
163
|
+
self.open = function (e) {
|
|
90
164
|
if (e.target.tagName === 'LI') {
|
|
91
165
|
// Avoid select something already selected
|
|
92
166
|
let index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
|
|
@@ -96,50 +170,78 @@ if (! lemonade && typeof (require) === 'function') {
|
|
|
96
170
|
}
|
|
97
171
|
}
|
|
98
172
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
173
|
+
self.create = function(item, position, select) {
|
|
174
|
+
// Create element
|
|
175
|
+
if (typeof(item) !== 'object') {
|
|
176
|
+
console.error('Item must be an object');
|
|
177
|
+
} else {
|
|
178
|
+
// Create DOM
|
|
179
|
+
item.el = document.createElement('div');
|
|
180
|
+
// Create from content
|
|
181
|
+
if (item.content) {
|
|
182
|
+
item.el.innerHTML = item.content;
|
|
183
|
+
}
|
|
104
184
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
185
|
+
// Add the new item in the end
|
|
186
|
+
if (typeof(position) === 'undefined' || position === null) {
|
|
187
|
+
// Mew item
|
|
188
|
+
position = self.data.length;
|
|
189
|
+
// Add in the end
|
|
190
|
+
self.data.push(item);
|
|
191
|
+
} else {
|
|
192
|
+
self.data.splice(position, 0, item);
|
|
193
|
+
}
|
|
194
|
+
// New position
|
|
195
|
+
if (select) {
|
|
196
|
+
// Refresh
|
|
197
|
+
init(self.data.indexOf(item));
|
|
198
|
+
} else {
|
|
199
|
+
init(self.selected);
|
|
200
|
+
}
|
|
112
201
|
}
|
|
113
202
|
}
|
|
114
|
-
return elements;
|
|
115
|
-
}
|
|
116
203
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
root.appendChild(elements.shift());
|
|
121
|
-
}
|
|
204
|
+
self.click = function() {
|
|
205
|
+
// Create a new item
|
|
206
|
+
self.create({ title: 'Untitled' }, null, true);
|
|
122
207
|
}
|
|
123
|
-
}
|
|
124
208
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
let elements = removeElements(root);
|
|
129
|
-
// Create the modal
|
|
130
|
-
let e = lemonade.render(Tabs, root, options);
|
|
131
|
-
// Add elements to the container
|
|
132
|
-
appendElements(e.children[1], elements);
|
|
209
|
+
self.onchange = function (property) {
|
|
210
|
+
if (property === 'selected') {
|
|
211
|
+
select(self.selected);
|
|
133
212
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return Tabs.call(this);
|
|
213
|
+
Dispatch.call(self, 'onopen', self, self.selected);
|
|
214
|
+
}
|
|
137
215
|
}
|
|
216
|
+
|
|
217
|
+
self.allowCreate = !! self.allowCreate;
|
|
218
|
+
|
|
219
|
+
return `<div class="lm-tabs" data-position="{{self.position}}" data-round="{{self.round}}">
|
|
220
|
+
<div role="tabs" class="lm-tabs-headers">
|
|
221
|
+
<ul :ref="self.headers" :loop="self.tabs" :selected="self.selected" onclick="self.open" onkeydown="self.keydown" onfocusin="self.open"><li class="lm-tab" tabindex="0" role="tab">{{self.title}}</li></ul>
|
|
222
|
+
<div data-visible="{{self.allowCreate}}" class="lm-tabs-insert-tab material-icons" role="insert-tab" onclick="self.click">add</div>
|
|
223
|
+
</div>
|
|
224
|
+
<div :ref="self.root" class="lm-tabs-content">${template}</div>
|
|
225
|
+
</div>`
|
|
138
226
|
}
|
|
139
227
|
|
|
140
228
|
lemonade.setComponents({ Tabs: Tabs });
|
|
141
229
|
|
|
142
230
|
lemonade.createWebComponent('tabs', Tabs);
|
|
143
231
|
|
|
144
|
-
return
|
|
232
|
+
return function (root, options) {
|
|
233
|
+
if (typeof (root) === 'object') {
|
|
234
|
+
if (typeof(options) !== 'object') {
|
|
235
|
+
options = {};
|
|
236
|
+
}
|
|
237
|
+
// Extract DOM references
|
|
238
|
+
extract(root, options);
|
|
239
|
+
// Create the modal
|
|
240
|
+
lemonade.render(Tabs, root, options);
|
|
241
|
+
// Return self
|
|
242
|
+
return options;
|
|
243
|
+
} else {
|
|
244
|
+
return Tabs.call(this);
|
|
245
|
+
}
|
|
246
|
+
};
|
|
145
247
|
})));
|
package/dist/style.css
CHANGED
|
@@ -2,47 +2,58 @@
|
|
|
2
2
|
padding: 15px 5px;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
.lm-tabs
|
|
5
|
+
.lm-tabs .lm-tabs-headers {
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
width: 100%;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.lm-tabs[data-position="center"] .lm-tabs-headers {
|
|
12
|
+
margin: 0 auto;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.lm-tabs .lm-tabs-headers > ul {
|
|
6
17
|
list-style-type: none;
|
|
7
18
|
display: flex;
|
|
8
19
|
margin: 0;
|
|
9
20
|
padding: 0;
|
|
10
|
-
|
|
21
|
+
align-items: center;
|
|
11
22
|
}
|
|
12
23
|
|
|
13
|
-
.lm-tabs > ul > li {
|
|
24
|
+
.lm-tabs .lm-tabs-headers > ul > li {
|
|
14
25
|
cursor: pointer;
|
|
15
26
|
user-select: none;
|
|
16
|
-
padding:
|
|
27
|
+
padding: 4px 24px;
|
|
17
28
|
border: 1px solid #ccc;
|
|
18
29
|
background-position: center;
|
|
19
30
|
transition: background 0.8s;
|
|
20
31
|
}
|
|
21
32
|
|
|
22
|
-
.lm-tabs > ul > li.selected {
|
|
33
|
+
.lm-tabs .lm-tabs-headers > ul > li.selected {
|
|
23
34
|
background-color: #eee;
|
|
24
35
|
color: #000;
|
|
25
36
|
}
|
|
26
37
|
|
|
27
|
-
.lm-tabs[data-round="true"] > ul > li:first-
|
|
38
|
+
.lm-tabs[data-round="true"] .lm-tabs-headers > ul > li:first-of-type {
|
|
28
39
|
border-top-left-radius: 3px;
|
|
29
40
|
border-bottom-left-radius: 3px;
|
|
30
41
|
}
|
|
31
42
|
|
|
32
|
-
.lm-tabs[data-round="true"] > ul > li:last-
|
|
43
|
+
.lm-tabs[data-round="true"] .lm-tabs-headers > ul > li:last-of-type {
|
|
33
44
|
border-top-right-radius: 3px;
|
|
34
45
|
border-bottom-right-radius: 3px;
|
|
35
46
|
}
|
|
36
47
|
|
|
37
|
-
.lm-tabs > ul > li:not(:first-child) {
|
|
38
|
-
border-left:
|
|
48
|
+
.lm-tabs .lm-tabs-headers > ul > li:not(:first-child) {
|
|
49
|
+
border-left: 1px solid transparent;
|
|
39
50
|
}
|
|
40
51
|
|
|
41
|
-
.lm-tabs > ul > li:hover {
|
|
52
|
+
.lm-tabs .lm-tabs-headers > ul > li:hover {
|
|
42
53
|
background: #eee radial-gradient(circle, transparent 1%, #eee 1%) center/15000%;
|
|
43
54
|
}
|
|
44
55
|
|
|
45
|
-
.lm-tabs > ul > li:active {
|
|
56
|
+
.lm-tabs .lm-tabs-headers > ul > li:active {
|
|
46
57
|
background-color: #ddd;
|
|
47
58
|
background-size: 100%;
|
|
48
59
|
transition: background 0s;
|
|
@@ -56,7 +67,12 @@
|
|
|
56
67
|
display: block;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
|
-
.lm-tabs
|
|
60
|
-
margin:
|
|
61
|
-
|
|
70
|
+
.lm-tabs-insert-tab {
|
|
71
|
+
margin-left: 5px;
|
|
72
|
+
color: #555;
|
|
73
|
+
cursor: pointer;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.lm-tabs div[data-visible='false'] {
|
|
77
|
+
display: none;
|
|
62
78
|
}
|