@programmerg/bs-elements 0.1.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/LICENSE.md +9 -0
- package/README.md +148 -0
- package/custom-elements.json +7773 -0
- package/dist/bs-elements.bundle.min.js +8 -0
- package/dist/bs-elements.bundle.min.js.map +1 -0
- package/dist/bs-elements.esm.js +1721 -0
- package/dist/bs-elements.esm.js.map +1 -0
- package/dist/bs-elements.min.js +2 -0
- package/dist/bs-elements.min.js.map +1 -0
- package/package.json +50 -0
- package/src/base/BsAccordion.js +116 -0
- package/src/base/BsAlert.js +91 -0
- package/src/base/BsButton.js +129 -0
- package/src/base/BsCarousel.js +216 -0
- package/src/base/BsCollapse.js +84 -0
- package/src/base/BsDropdown.js +98 -0
- package/src/base/BsModal.js +204 -0
- package/src/base/BsOffcanvas.js +157 -0
- package/src/base/BsPopover.js +31 -0
- package/src/base/BsTab.js +69 -0
- package/src/base/BsToast.js +163 -0
- package/src/base/BsTooltip.js +118 -0
- package/src/core/BsElement.js +81 -0
- package/src/core/ReactiveElement.js +183 -0
- package/src/extra/BsCalendar.js +14 -0
- package/src/extra/BsCombobox.js +14 -0
- package/src/extra/BsForm.js +152 -0
- package/src/extra/BsInput.js +209 -0
- package/src/extra/BsTable.js +210 -0
- package/src/extra/BsTabs.js +0 -0
- package/src/extra/BsToastManager.js +0 -0
- package/src/extra/BsTree.js +14 -0
- package/src/extra/BsUploader.js +154 -0
- package/src/index.js +12 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Dropdown } from "bootstrap";
|
|
2
|
+
import BsElement from "../core/BsElement.js";
|
|
3
|
+
|
|
4
|
+
export default class BsDropdown extends BsElement {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
autoClose: {
|
|
9
|
+
description: "A boolean indicating whether the Dropdown should automatically close when an item is selected.",
|
|
10
|
+
type: Boolean,
|
|
11
|
+
default: true,
|
|
12
|
+
attribute: "data-bs-auto-close"
|
|
13
|
+
},
|
|
14
|
+
direction: {
|
|
15
|
+
description: "The direction of the Dropdown menu",
|
|
16
|
+
type: String,
|
|
17
|
+
default: "down",
|
|
18
|
+
values: ["down", "start", "end", "up", "down-center", "up-center"]
|
|
19
|
+
},
|
|
20
|
+
open: {
|
|
21
|
+
description: "A boolean indicating whether the Dropdown is currently open.",
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: false
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static get bs() {
|
|
29
|
+
return Dropdown;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
constructor() {
|
|
33
|
+
super();
|
|
34
|
+
|
|
35
|
+
// this is an external state managed by bootstrap
|
|
36
|
+
Object.defineProperty(this.constructor.prototype, "open", {
|
|
37
|
+
get() {
|
|
38
|
+
return this.classList.contains("show");
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
hide() {
|
|
44
|
+
return this.bs?.hide();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
show() {
|
|
48
|
+
return this.bs?.show();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
toggle() {
|
|
52
|
+
return this.bs?.toggle();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
update() {
|
|
56
|
+
return this.bs?.update();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
firstUpdated() {
|
|
60
|
+
this.classList.add("dropdown");
|
|
61
|
+
|
|
62
|
+
// Ensure toggle has the proper data attribute
|
|
63
|
+
const toggle = this.querySelector(
|
|
64
|
+
`:scope > [data-bs-toggle="dropdown"], :scope > .dropdown-toggle`
|
|
65
|
+
);
|
|
66
|
+
if (toggle && !toggle.hasAttribute("data-bs-toggle")) {
|
|
67
|
+
toggle.setAttribute("data-bs-toggle", "dropdown");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
this._fixMarkup();
|
|
71
|
+
this._updateDirectionState();
|
|
72
|
+
this._updateOpenState(true);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
_fixMarkup() {
|
|
76
|
+
// Ensure bs-dropdown-menu children receive Bootstrap class
|
|
77
|
+
const menu = this.querySelector(":scope > div, :scope > .dropdown-menu");
|
|
78
|
+
if (menu && !menu.classList.contains("dropdown-menu")) {
|
|
79
|
+
menu.classList.add("dropdown-menu");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_updateDirectionState() {
|
|
84
|
+
this.classList.remove(
|
|
85
|
+
...this.constructor.properties
|
|
86
|
+
.direction.values.map(v => "drop" + v)
|
|
87
|
+
);
|
|
88
|
+
this.classList.add("drop" + this.direction);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
_updateOpenState(isFirstUpdate = false) {
|
|
92
|
+
if (isFirstUpdate) this.classList.toggle("show", this.__propValues['open']);
|
|
93
|
+
else this.toggle();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
customElements.define("bs-dropdown", BsDropdown);
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { Modal } from "bootstrap";
|
|
2
|
+
import BsElement from "../core/BsElement.js";
|
|
3
|
+
|
|
4
|
+
export default class BsModal extends BsElement {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
focus: {
|
|
9
|
+
description: "Automatically puts focus on the modal with it first opens.",
|
|
10
|
+
type: Boolean,
|
|
11
|
+
default: false,
|
|
12
|
+
attribute: "data-bs-focus"
|
|
13
|
+
},
|
|
14
|
+
backdrop: {
|
|
15
|
+
description: "Controls the visibility of the modal backdrop.",
|
|
16
|
+
type: Boolean,
|
|
17
|
+
default: true,
|
|
18
|
+
attribute: "data-bs-backdrop"
|
|
19
|
+
},
|
|
20
|
+
centered: {
|
|
21
|
+
description: "Auto-positioning of the modal to ensure its centered in the viewport.",
|
|
22
|
+
type: Boolean,
|
|
23
|
+
default: false
|
|
24
|
+
},
|
|
25
|
+
fade: {
|
|
26
|
+
description: "Control the fade effect when opening or closing the modal.",
|
|
27
|
+
type: Boolean,
|
|
28
|
+
default: true
|
|
29
|
+
},
|
|
30
|
+
fullscreen: {
|
|
31
|
+
description: "Determines whether or no the modal is rendered in fullscreen mode.",
|
|
32
|
+
type: String,
|
|
33
|
+
default: "",
|
|
34
|
+
values: ["true", "sm", "md", "lg", "xl", "xxl"]
|
|
35
|
+
},
|
|
36
|
+
header: {
|
|
37
|
+
description: "Customize the modal header content.",
|
|
38
|
+
type: String,
|
|
39
|
+
default: undefined
|
|
40
|
+
},
|
|
41
|
+
open: {
|
|
42
|
+
description: "Used to control the modal state",
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: false
|
|
45
|
+
},
|
|
46
|
+
keyboard: {
|
|
47
|
+
description: "Ccontrol whether the modal can be closed using the ESC key.",
|
|
48
|
+
type: Boolean,
|
|
49
|
+
default: true,
|
|
50
|
+
attribute: "data-bs-keyboard"
|
|
51
|
+
},
|
|
52
|
+
scrollable: {
|
|
53
|
+
description: "Determines if the modal content should be scrollable.",
|
|
54
|
+
type: Boolean,
|
|
55
|
+
default: false
|
|
56
|
+
},
|
|
57
|
+
size: {
|
|
58
|
+
description: "Specify the size of the modal.",
|
|
59
|
+
type: String,
|
|
60
|
+
default: "",
|
|
61
|
+
values: ["sm", "lg", "xl"]
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static get bs() {
|
|
67
|
+
return Modal;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
constructor() {
|
|
71
|
+
super();
|
|
72
|
+
|
|
73
|
+
// this is an external state managed by bootstrap
|
|
74
|
+
Object.defineProperty(this.constructor.prototype, "open", {
|
|
75
|
+
get() {
|
|
76
|
+
return this.classList.contains("show");
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
handleUpdate() {
|
|
82
|
+
return this.bs?.handleUpdate();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
hide() {
|
|
86
|
+
return this.bs?.hide();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
show() {
|
|
90
|
+
return this.bs?.show();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
toggle() {
|
|
94
|
+
return this.bs?.toggle();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
firstUpdated() {
|
|
98
|
+
this.classList.add("modal");
|
|
99
|
+
if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "-1");
|
|
100
|
+
|
|
101
|
+
this._fixMarkup();
|
|
102
|
+
this._updateFadeState();
|
|
103
|
+
this._updateCenteredState();
|
|
104
|
+
this._updateScrollableState();
|
|
105
|
+
this._updateSizeState();
|
|
106
|
+
this._updateFullscreenState();
|
|
107
|
+
this._updateOpenState(true);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_fixMarkup() {
|
|
111
|
+
let dialog = this.querySelector(":scope > .modal-dialog");
|
|
112
|
+
if (dialog) return;
|
|
113
|
+
|
|
114
|
+
dialog = document.createElement("div");
|
|
115
|
+
dialog.classList.add("modal-dialog");
|
|
116
|
+
|
|
117
|
+
const content = document.createElement("div");
|
|
118
|
+
content.classList.add("modal-content");
|
|
119
|
+
|
|
120
|
+
let header = this.querySelector(":scope > .modal-header");
|
|
121
|
+
if (!header) {
|
|
122
|
+
header = document.createElement("div");
|
|
123
|
+
header.classList.add("modal-header");
|
|
124
|
+
header.insertAdjacentHTML("afterbegin", `<h5 class="modal-title">${this.header}</h5>`);
|
|
125
|
+
}
|
|
126
|
+
content.appendChild(header);
|
|
127
|
+
|
|
128
|
+
if (header.querySelector(".btn-close")) {
|
|
129
|
+
header.insertAdjacentHTML("beforeend",
|
|
130
|
+
`<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>`
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let body = this.querySelector(":scope > .modal-body");
|
|
135
|
+
if (!body) {
|
|
136
|
+
body = document.createElement("div");
|
|
137
|
+
body.classList.add("modal-body");
|
|
138
|
+
}
|
|
139
|
+
content.appendChild(body);
|
|
140
|
+
|
|
141
|
+
let footer = this.querySelector(":scope > .modal-footer");
|
|
142
|
+
if (footer) {
|
|
143
|
+
content.appendChild(footer);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
while (this.firstChild) {
|
|
147
|
+
body.appendChild(this.firstChild);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
dialog.appendChild(content);
|
|
151
|
+
this.appendChild(dialog);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_updateHeaderState() {
|
|
155
|
+
const title = this.querySelector(":scope > .modal-dialog > .modal-header > .modal-title");
|
|
156
|
+
if (title) {
|
|
157
|
+
title.textContent = this.header;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
_updateFadeState() {
|
|
162
|
+
this.classList.toggle("fade", this.fade);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_updateCenteredState() {
|
|
166
|
+
const dialog = this.querySelector(":scope > .modal-dialog");
|
|
167
|
+
dialog?.classList.toggle("modal-dialog-centered", this.centered);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
_updateScrollableState() {
|
|
171
|
+
const dialog = this.querySelector(":scope > .modal-dialog");
|
|
172
|
+
dialog?.classList.toggle("modal-dialog-scrollable", this.scrollable);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
_updateSizeState() {
|
|
176
|
+
const dialog = this.querySelector(":scope > .modal-dialog");
|
|
177
|
+
dialog?.classList.remove(
|
|
178
|
+
...this.constructor.properties
|
|
179
|
+
.size.values.map(v => "modal-" + v)
|
|
180
|
+
);
|
|
181
|
+
if (this.size) dialog?.classList.add(`modal-${this.size}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
_updateFullscreenState() {
|
|
185
|
+
const dialog = this.querySelector(":scope > .modal-dialog");
|
|
186
|
+
dialog?.classList.remove(
|
|
187
|
+
...this.constructor.properties
|
|
188
|
+
.fullscreen.values.map(v => "modal-fullscreen-" + v + "-down")
|
|
189
|
+
);
|
|
190
|
+
if (this.fullscreen) dialog?.classList.add(
|
|
191
|
+
this.fullscreen === "true"
|
|
192
|
+
? "modal-fullscreen"
|
|
193
|
+
: `modal-fullscreen-${this.fullscreen}-down`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
_updateOpenState(isFirstUpdate = false) {
|
|
198
|
+
if (isFirstUpdate) this.classList.toggle("show", this.__propValues['open']);
|
|
199
|
+
else this.toggle();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
customElements.define("bs-modal", BsModal);
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Offcanvas } from "bootstrap";
|
|
2
|
+
import BsElement from "../core/BsElement.js";
|
|
3
|
+
|
|
4
|
+
export default class BsOffcanvas extends BsElement {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
backdrop: {
|
|
9
|
+
description: "Controls whether the backdrop is displayed behind the offcanvas.",
|
|
10
|
+
type: Boolean,
|
|
11
|
+
default: true,
|
|
12
|
+
attribute: "data-bs-backdrop"
|
|
13
|
+
},
|
|
14
|
+
fade: {
|
|
15
|
+
description: "Controls whether to use a fade animation when opening/closing the offcanvas.",
|
|
16
|
+
type: Boolean,
|
|
17
|
+
default: true
|
|
18
|
+
},
|
|
19
|
+
header: {
|
|
20
|
+
description: "The header content of the offcanvas.",
|
|
21
|
+
type: String,
|
|
22
|
+
default: ""
|
|
23
|
+
},
|
|
24
|
+
open: {
|
|
25
|
+
description: "Used to control the modal state",
|
|
26
|
+
type: Boolean,
|
|
27
|
+
default: false
|
|
28
|
+
},
|
|
29
|
+
keyboard: {
|
|
30
|
+
description: "Controls whether keyboard interaction is enabled for closing the offcanvas.",
|
|
31
|
+
type: Boolean,
|
|
32
|
+
default: true,
|
|
33
|
+
attribute: "data-bs-keyboard"
|
|
34
|
+
},
|
|
35
|
+
placement: {
|
|
36
|
+
description: "The placement of the offcanvas.",
|
|
37
|
+
type: String,
|
|
38
|
+
default: "start",
|
|
39
|
+
values: ["start", "end", "top", "bottom"]
|
|
40
|
+
},
|
|
41
|
+
scroll: {
|
|
42
|
+
description: "Controls whether to allow scrolling of the body when the offcanvas is open.",
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: false,
|
|
45
|
+
attribute: "data-bs-scroll"
|
|
46
|
+
},
|
|
47
|
+
size: {
|
|
48
|
+
description: "Specify the size of the modal.",
|
|
49
|
+
type: String,
|
|
50
|
+
default: "",
|
|
51
|
+
values: ["sm", "md", "lg", "xl", "xxl"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static get bs() {
|
|
57
|
+
return Offcanvas;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
constructor() {
|
|
61
|
+
super();
|
|
62
|
+
|
|
63
|
+
// this is an external state managed by bootstrap
|
|
64
|
+
Object.defineProperty(this.constructor.prototype, "open", {
|
|
65
|
+
get() {
|
|
66
|
+
return this.classList.contains("show");
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
hide() {
|
|
72
|
+
return this.bs?.hide();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
show() {
|
|
76
|
+
return this.bs?.show();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
toggle() {
|
|
80
|
+
return this.bs?.toggle();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
firstUpdated() {
|
|
84
|
+
this.classList.add("offcanvas");
|
|
85
|
+
if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "-1");
|
|
86
|
+
|
|
87
|
+
this._fixMarkup();
|
|
88
|
+
this._updateFadeState();
|
|
89
|
+
this._updatePlacementState();
|
|
90
|
+
this._updateSizeState();
|
|
91
|
+
this._updateOpenState(true);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
_fixMarkup() {
|
|
95
|
+
let header = this.querySelector(":scope > .offcanvas-header");
|
|
96
|
+
if (!header) {
|
|
97
|
+
header = document.createElement("div");
|
|
98
|
+
header.classList.add("offcanvas-header");
|
|
99
|
+
header.insertAdjacentHTML("afterbegin", `<h5 class="offcanvas-title">${this.header ?? ""}</h5>`);
|
|
100
|
+
header.insertAdjacentHTML("beforeend",
|
|
101
|
+
`<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>`
|
|
102
|
+
);
|
|
103
|
+
this.appendChild(header);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (!header.querySelector(".btn-close")) {
|
|
107
|
+
header.insertAdjacentHTML("beforeend",
|
|
108
|
+
`<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let body = this.querySelector(":scope > .offcanvas-body");
|
|
113
|
+
if (!body) {
|
|
114
|
+
body = document.createElement("div");
|
|
115
|
+
body.classList.add("offcanvas-body");
|
|
116
|
+
this.appendChild(body);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for (const node of Array.from(this.childNodes)) {
|
|
120
|
+
if (node === header || node === body) continue;
|
|
121
|
+
body.appendChild(node)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
_updateHeaderState() {
|
|
126
|
+
const title = this.querySelector(":scope > .offcanvas-header > .offcanvas-title");
|
|
127
|
+
if (title) title.textContent = this.header ?? "";
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
_updateFadeState() {
|
|
131
|
+
this.classList.toggle("fade", this.fade);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
_updatePlacementState() {
|
|
135
|
+
this.classList.remove(
|
|
136
|
+
...this.constructor.properties
|
|
137
|
+
.placement.values.map(v => "offcanvas-" + v)
|
|
138
|
+
);
|
|
139
|
+
if (this.placement) this.classList.add(`offcanvas-${this.placement}`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
_updateSizeState() {
|
|
143
|
+
this.classList.remove(
|
|
144
|
+
...this.constructor.properties
|
|
145
|
+
.size.values.map(v => "offcanvas-" + v)
|
|
146
|
+
);
|
|
147
|
+
if (this.size) this.classList.add(`offcanvas-${this.size}`);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
_updateOpenState(isFirstUpdate = false) {
|
|
151
|
+
if (isFirstUpdate) this.classList.toggle("show", this.__propValues['open']);
|
|
152
|
+
else this.toggle();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
customElements.define("bs-offcanvas", BsOffcanvas);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Popover } from "bootstrap";
|
|
2
|
+
import BsTooltip from "./BsTooltip.js";
|
|
3
|
+
|
|
4
|
+
export default class BsPopover extends BsTooltip {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
...super.constructor.properties,
|
|
9
|
+
content: {
|
|
10
|
+
description: "The content to be displayed within the popover.",
|
|
11
|
+
type: String,
|
|
12
|
+
default: "",
|
|
13
|
+
attribute: "data-bs-content"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static get bs() {
|
|
19
|
+
return Popover;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
firstUpdated() {
|
|
23
|
+
if (!this.hasAttribute("data-bs-toggle")) {
|
|
24
|
+
this.setAttribute("data-bs-toggle", "popover");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
this._updateOpenState(true);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
customElements.define("bs-popover", BsPopover);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Tab } from "bootstrap";
|
|
2
|
+
import BsElement from "../core/BsElement.js";
|
|
3
|
+
|
|
4
|
+
export default class BsTab extends BsElement {
|
|
5
|
+
|
|
6
|
+
static get properties() {
|
|
7
|
+
return {
|
|
8
|
+
fade: {
|
|
9
|
+
description: "Control the fade effect when opening or closing the modal.",
|
|
10
|
+
type: Boolean,
|
|
11
|
+
default: true
|
|
12
|
+
},
|
|
13
|
+
active: {
|
|
14
|
+
description: "Whether the element is active or not",
|
|
15
|
+
type: Boolean,
|
|
16
|
+
default: false
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static get bs() {
|
|
22
|
+
return Tab;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
|
|
28
|
+
// this is an external state managed by bootstrap
|
|
29
|
+
Object.defineProperty(this.constructor.prototype, "active", {
|
|
30
|
+
get() {
|
|
31
|
+
return this.classList.contains("active");
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
show() {
|
|
37
|
+
return this.bs?.show();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
firstUpdated() {
|
|
41
|
+
this.classList.add("tab-pane");
|
|
42
|
+
if (!this.hasAttribute("role")) this.setAttribute("role", "tabpanel");
|
|
43
|
+
if (!this.hasAttribute("tabindex")) this.setAttribute("tabindex", "0");
|
|
44
|
+
|
|
45
|
+
this._updateFadeState();
|
|
46
|
+
this._updateActiveState(true);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_updateFadeState() {
|
|
50
|
+
this.classList.toggle("fade", this.fade);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
_updateActiveState(isFirstUpdate = false) {
|
|
54
|
+
const newState = this.__propValues["active"];
|
|
55
|
+
if (isFirstUpdate) {
|
|
56
|
+
this.classList.toggle("show", newState);
|
|
57
|
+
this.classList.toggle("active", newState);
|
|
58
|
+
} else {
|
|
59
|
+
if (newState) this.show();
|
|
60
|
+
else {
|
|
61
|
+
this.classList.toggle("show", false);
|
|
62
|
+
this.classList.toggle("active", false);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
customElements.define("bs-tab", BsTab);
|