@bluevolt-tech/lumen 1.3.2
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/README.md +286 -0
- package/assets/fonts/fonts.css +25 -0
- package/assets/icons/.gitkeep +0 -0
- package/assets/icons/edit.svg +3 -0
- package/assets/images/.gitkeep +0 -0
- package/assets/images/bluevolt-logo.png +0 -0
- package/dist/assets/fonts/fonts.css +25 -0
- package/dist/assets/icons/.gitkeep +0 -0
- package/dist/assets/icons/edit.svg +3 -0
- package/dist/assets/images/.gitkeep +0 -0
- package/dist/assets/images/bluevolt-logo.png +0 -0
- package/dist/components/bv-avatar/bv-avatar.d.ts +13 -0
- package/dist/components/bv-avatar/bv-avatar.js +81 -0
- package/dist/components/bv-badge/bv-badge.d.ts +11 -0
- package/dist/components/bv-badge/bv-badge.js +58 -0
- package/dist/components/bv-button/bv-button.d.ts +23 -0
- package/dist/components/bv-button/bv-button.js +395 -0
- package/dist/components/bv-category-pill/bv-category-pill.d.ts +11 -0
- package/dist/components/bv-category-pill/bv-category-pill.js +61 -0
- package/dist/components/bv-checkbox/bv-checkbox.d.ts +14 -0
- package/dist/components/bv-checkbox/bv-checkbox.js +89 -0
- package/dist/components/bv-chip/bv-chip.d.ts +11 -0
- package/dist/components/bv-chip/bv-chip.js +72 -0
- package/dist/components/bv-course-detail/bv-course-detail.d.ts +28 -0
- package/dist/components/bv-course-detail/bv-course-detail.js +269 -0
- package/dist/components/bv-course-detail-modal/bv-course-detail-modal.d.ts +35 -0
- package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +1455 -0
- package/dist/components/bv-course-grid-card/bv-course-grid-card.d.ts +12 -0
- package/dist/components/bv-course-grid-card/bv-course-grid-card.js +578 -0
- package/dist/components/bv-course-list-card/bv-course-list-card.d.ts +12 -0
- package/dist/components/bv-course-list-card/bv-course-list-card.js +585 -0
- package/dist/components/bv-course-outline/bv-course-outline.d.ts +49 -0
- package/dist/components/bv-course-outline/bv-course-outline.js +488 -0
- package/dist/components/bv-empty-state/bv-empty-state.d.ts +10 -0
- package/dist/components/bv-empty-state/bv-empty-state.js +69 -0
- package/dist/components/bv-filter-dropdown/bv-filter-dropdown.d.ts +26 -0
- package/dist/components/bv-filter-dropdown/bv-filter-dropdown.js +164 -0
- package/dist/components/bv-filter-panel/bv-filter-panel.d.ts +25 -0
- package/dist/components/bv-filter-panel/bv-filter-panel.js +222 -0
- package/dist/components/bv-icon/bv-icon.d.ts +10 -0
- package/dist/components/bv-icon/bv-icon.js +122 -0
- package/dist/components/bv-icon/icons.d.ts +3 -0
- package/dist/components/bv-modal/bv-modal.d.ts +13 -0
- package/dist/components/bv-modal/bv-modal.js +104 -0
- package/dist/components/bv-page-title/bv-page-title.d.ts +4 -0
- package/dist/components/bv-page-title/bv-page-title.js +33 -0
- package/dist/components/bv-pagination/bv-pagination.d.ts +20 -0
- package/dist/components/bv-pagination/bv-pagination.js +139 -0
- package/dist/components/bv-portal-header/bv-portal-header.d.ts +12 -0
- package/dist/components/bv-portal-header/bv-portal-header.js +854 -0
- package/dist/components/bv-portal-layout/bv-portal-layout.d.ts +6 -0
- package/dist/components/bv-portal-layout/bv-portal-layout.js +39 -0
- package/dist/components/bv-progress-bar/bv-progress-bar.d.ts +11 -0
- package/dist/components/bv-progress-bar/bv-progress-bar.js +61 -0
- package/dist/components/bv-promo-banner/bv-promo-banner.d.ts +12 -0
- package/dist/components/bv-promo-banner/bv-promo-banner.js +79 -0
- package/dist/components/bv-radio/bv-radio.d.ts +11 -0
- package/dist/components/bv-radio/bv-radio.js +78 -0
- package/dist/components/bv-searchbox/bv-searchbox.d.ts +10 -0
- package/dist/components/bv-searchbox/bv-searchbox.js +68 -0
- package/dist/components/bv-star-rating/bv-star-rating.d.ts +11 -0
- package/dist/components/bv-star-rating/bv-star-rating.js +67 -0
- package/dist/components/bv-table/bv-table.d.ts +5 -0
- package/dist/components/bv-table/bv-table.js +72 -0
- package/dist/components/bv-toggle/bv-toggle.d.ts +11 -0
- package/dist/components/bv-toggle/bv-toggle.js +72 -0
- package/dist/components/bv-user-row/bv-user-row.d.ts +12 -0
- package/dist/components/bv-user-row/bv-user-row.js +574 -0
- package/dist/components/bv-view-switcher/bv-view-switcher.d.ts +11 -0
- package/dist/components/bv-view-switcher/bv-view-switcher.js +91 -0
- package/dist/preview/index.html +76 -0
- package/dist/storybook/stories/screens/course-catalog.data.d.ts +28 -0
- package/dist/storybook/stories/screens/course-catalog.data.js +301 -0
- package/dist/themes/base.css +66 -0
- package/dist/themes/layouts.css +35 -0
- package/package.json +181 -0
- package/themes/base.css +66 -0
- package/themes/layouts.css +35 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-modal/bv-modal.css
|
|
2
|
+
var bv_modal_default = '/* \u2500\u2500 Public theming API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n Apps can override per-instance:\n\n HTML: <bv-modal style="--bv-modal-width: 600px;">\n Angular: <bv-modal [style.--bv-modal-bg]="bgColor">\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n:host {\n --bv-modal-width: 800px;\n --bv-modal-bg: var(--bv-color-neutral-0);\n --bv-modal-radius: var(--bv-radius-xl);\n --bv-modal-title-color: #101828;\n --bv-modal-backdrop: rgba(16, 24, 40, 0.6);\n --bv-modal-body-max-height: none;\n}\n\ndialog {\n padding: 0;\n border: none;\n border-radius: var(--bv-modal-radius);\n background: transparent;\n width: var(--bv-modal-width);\n max-width: min(var(--bv-modal-width), calc(100vw - 32px));\n outline: none;\n}\n\ndialog::backdrop {\n background: var(--bv-modal-backdrop);\n}\n\n.panel {\n display: flex;\n width: 100%;\n padding: 20px 16px;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n gap: 20px;\n border-radius: var(--bv-modal-radius);\n background: var(--bv-modal-bg);\n box-sizing: border-box;\n}\n\n/* \u2500\u2500 Header \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.header {\n display: flex;\n width: 100%;\n align-items: center;\n justify-content: space-between;\n}\n\n.title {\n margin: 0;\n color: var(--bv-modal-title-color);\n font-family: var(--bv-font-family-base);\n font-size: 24px;\n font-style: normal;\n font-weight: var(--bv-font-weight-medium);\n line-height: 32px;\n}\n\n.close-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: none;\n border: none;\n border-radius: var(--bv-radius-md);\n cursor: pointer;\n color: var(--bv-color-neutral-500);\n font-size: 18px;\n line-height: 1;\n flex-shrink: 0;\n transition:\n color var(--bv-transition-fast),\n background var(--bv-transition-fast);\n}\n\n.close-btn:hover {\n color: var(--bv-color-neutral-800);\n background: var(--bv-color-neutral-100);\n}\n\n/* \u2500\u2500 Separator \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.separator {\n width: 100%;\n border: none;\n border-top: 1px solid var(--bv-color-neutral-200);\n margin: 0;\n}\n\n/* \u2500\u2500 Body \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.body {\n width: 100%;\n max-height: var(--bv-modal-body-max-height);\n overflow-y: auto;\n color: var(--bv-color-neutral-600);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n line-height: 20px;\n}\n\n/* \u2500\u2500 Footer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500*/\n\n.footer {\n width: 100%;\n}\n';
|
|
3
|
+
|
|
4
|
+
// components/bv-modal/bv-modal.ts
|
|
5
|
+
var BvModal = class extends HTMLElement {
|
|
6
|
+
static observedAttributes = ["title", "open"];
|
|
7
|
+
_dialog = null;
|
|
8
|
+
_titleEl = null;
|
|
9
|
+
_rendered = false;
|
|
10
|
+
constructor() {
|
|
11
|
+
super();
|
|
12
|
+
this.attachShadow({ mode: "open" });
|
|
13
|
+
if (typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
|
|
14
|
+
const sheet = new CSSStyleSheet();
|
|
15
|
+
sheet.replaceSync(bv_modal_default);
|
|
16
|
+
this.shadowRoot.adoptedStyleSheets = [sheet];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
connectedCallback() {
|
|
20
|
+
this._render();
|
|
21
|
+
}
|
|
22
|
+
disconnectedCallback() {
|
|
23
|
+
var _a;
|
|
24
|
+
(_a = this._dialog) == null ? void 0 : _a.close();
|
|
25
|
+
}
|
|
26
|
+
attributeChangedCallback(name, _old, newVal) {
|
|
27
|
+
if (!this._rendered) return;
|
|
28
|
+
if (name === "title" && this._titleEl) {
|
|
29
|
+
this._titleEl.textContent = newVal ?? "";
|
|
30
|
+
}
|
|
31
|
+
if (name === "open") {
|
|
32
|
+
this._syncOpen();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
_syncOpen() {
|
|
36
|
+
if (!this._dialog) return;
|
|
37
|
+
if (this.hasAttribute("open")) {
|
|
38
|
+
if (!this._dialog.open) this._dialog.showModal();
|
|
39
|
+
} else {
|
|
40
|
+
if (this._dialog.open) this._dialog.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
_close() {
|
|
44
|
+
this.removeAttribute("open");
|
|
45
|
+
this.dispatchEvent(new CustomEvent("bv-close", { bubbles: true, composed: true }));
|
|
46
|
+
}
|
|
47
|
+
_render() {
|
|
48
|
+
if (this._rendered) return;
|
|
49
|
+
this._rendered = true;
|
|
50
|
+
const shadow = this.shadowRoot;
|
|
51
|
+
if (!shadow.adoptedStyleSheets.length) {
|
|
52
|
+
const style = document.createElement("style");
|
|
53
|
+
style.textContent = bv_modal_default;
|
|
54
|
+
shadow.appendChild(style);
|
|
55
|
+
}
|
|
56
|
+
const dialog = document.createElement("dialog");
|
|
57
|
+
this._dialog = dialog;
|
|
58
|
+
dialog.addEventListener("click", (e) => {
|
|
59
|
+
if (e.target === dialog) this._close();
|
|
60
|
+
});
|
|
61
|
+
dialog.addEventListener("cancel", (e) => {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
this._close();
|
|
64
|
+
});
|
|
65
|
+
const panel = document.createElement("div");
|
|
66
|
+
panel.className = "panel";
|
|
67
|
+
const header = document.createElement("div");
|
|
68
|
+
header.className = "header";
|
|
69
|
+
const titleEl = document.createElement("h2");
|
|
70
|
+
titleEl.className = "title";
|
|
71
|
+
titleEl.textContent = this.getAttribute("title") ?? "";
|
|
72
|
+
this._titleEl = titleEl;
|
|
73
|
+
const closeBtn = document.createElement("button");
|
|
74
|
+
closeBtn.className = "close-btn";
|
|
75
|
+
closeBtn.setAttribute("aria-label", "Close");
|
|
76
|
+
closeBtn.textContent = "\u2715";
|
|
77
|
+
closeBtn.addEventListener("click", () => this._close());
|
|
78
|
+
header.append(titleEl, closeBtn);
|
|
79
|
+
const separator = document.createElement("hr");
|
|
80
|
+
separator.className = "separator";
|
|
81
|
+
const body = document.createElement("div");
|
|
82
|
+
body.className = "body";
|
|
83
|
+
body.appendChild(document.createElement("slot"));
|
|
84
|
+
const footer = document.createElement("div");
|
|
85
|
+
footer.className = "footer";
|
|
86
|
+
footer.hidden = true;
|
|
87
|
+
const footerSlot = document.createElement("slot");
|
|
88
|
+
footerSlot.name = "footer";
|
|
89
|
+
footerSlot.addEventListener("slotchange", () => {
|
|
90
|
+
footer.hidden = footerSlot.assignedNodes().length === 0;
|
|
91
|
+
});
|
|
92
|
+
footer.appendChild(footerSlot);
|
|
93
|
+
panel.append(header, separator, body, footer);
|
|
94
|
+
dialog.appendChild(panel);
|
|
95
|
+
shadow.appendChild(dialog);
|
|
96
|
+
this._syncOpen();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
if (!customElements.get("bv-modal")) {
|
|
100
|
+
customElements.define("bv-modal", BvModal);
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
BvModal
|
|
104
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-page-title/bv-page-title.css
|
|
2
|
+
var bv_page_title_default = ":host {\n display: block;\n}\n\nh1 {\n margin: 0;\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-2xl);\n font-weight: var(--bv-font-weight-medium);\n line-height: 1.2;\n color: var(--bv-color-neutral-900);\n}\n";
|
|
3
|
+
|
|
4
|
+
// components/bv-page-title/bv-page-title.ts
|
|
5
|
+
var BvPageTitle = class extends HTMLElement {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
this.attachShadow({ mode: "open" });
|
|
9
|
+
if ("replaceSync" in CSSStyleSheet.prototype) {
|
|
10
|
+
const sheet = new CSSStyleSheet();
|
|
11
|
+
sheet.replaceSync(bv_page_title_default);
|
|
12
|
+
this.shadowRoot.adoptedStyleSheets = [sheet];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
connectedCallback() {
|
|
16
|
+
if (this.shadowRoot.childElementCount > (this.shadowRoot.adoptedStyleSheets.length ? 0 : 1))
|
|
17
|
+
return;
|
|
18
|
+
if (!this.shadowRoot.adoptedStyleSheets.length) {
|
|
19
|
+
const s = document.createElement("style");
|
|
20
|
+
s.textContent = bv_page_title_default;
|
|
21
|
+
this.shadowRoot.appendChild(s);
|
|
22
|
+
}
|
|
23
|
+
const h1 = document.createElement("h1");
|
|
24
|
+
h1.appendChild(document.createElement("slot"));
|
|
25
|
+
this.shadowRoot.appendChild(h1);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
if (!customElements.get("bv-page-title")) {
|
|
29
|
+
customElements.define("bv-page-title", BvPageTitle);
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
BvPageTitle
|
|
33
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare class BvPagination extends HTMLElement {
|
|
2
|
+
static readonly observedAttributes: string[];
|
|
3
|
+
private _rendered;
|
|
4
|
+
private _pagesEl;
|
|
5
|
+
private _prevBtn;
|
|
6
|
+
private _nextBtn;
|
|
7
|
+
private _rangeEl;
|
|
8
|
+
constructor();
|
|
9
|
+
connectedCallback(): void;
|
|
10
|
+
attributeChangedCallback(): void;
|
|
11
|
+
get page(): number;
|
|
12
|
+
get totalPages(): number;
|
|
13
|
+
get total(): number;
|
|
14
|
+
get pageSize(): number;
|
|
15
|
+
get siblings(): number;
|
|
16
|
+
private _go;
|
|
17
|
+
private _render;
|
|
18
|
+
private _update;
|
|
19
|
+
private _pageRange;
|
|
20
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-pagination/bv-pagination.css
|
|
2
|
+
var bv_pagination_default = ":host {\n display: block;\n}\n\n.wrap {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n font-family: var(--bv-font-family-base);\n}\n\n/* Shared button base */\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border: 1px solid transparent;\n border-radius: var(--bv-radius-lg);\n background: transparent;\n font-family: inherit;\n font-size: var(--bv-font-size-sm);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast);\n}\n\n/* Prev / Next buttons */\n.nav-btn {\n gap: var(--bv-spacing-xs);\n height: 36px;\n padding: 0 var(--bv-spacing-sm);\n border-color: var(--bv-color-neutral-300);\n background: var(--bv-color-neutral-0);\n color: var(--bv-color-neutral-700);\n font-weight: var(--bv-font-weight-semibold);\n box-shadow: var(--bv-shadow-sm);\n white-space: nowrap;\n}\n\n.nav-btn:hover:not(:disabled) {\n background: var(--bv-color-neutral-100);\n}\n\n.nav-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.nav-icon {\n width: 20px;\n height: 20px;\n flex-shrink: 0;\n}\n\n/* Page number buttons */\n.pages {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.page-btn {\n width: 40px;\n height: 40px;\n color: var(--bv-color-neutral-600);\n font-weight: var(--bv-font-weight-medium);\n}\n\n.page-btn:hover:not(.active) {\n background: var(--bv-color-neutral-100);\n}\n\n.page-btn.active {\n background: var(--bv-color-neutral-100);\n color: var(--bv-color-neutral-900);\n cursor: default;\n}\n\n.ellipsis {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n font-size: var(--bv-font-size-sm);\n color: var(--bv-color-neutral-400);\n}\n\n/* Right section */\n.right-section {\n display: flex;\n align-items: center;\n gap: var(--bv-spacing-md);\n}\n\n.range-label {\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-600);\n white-space: nowrap;\n}\n";
|
|
3
|
+
|
|
4
|
+
// components/bv-pagination/bv-pagination.ts
|
|
5
|
+
var PREV_ICON = `<svg class="nav-icon" viewBox="0 0 20 20" fill="none"><path d="M12.5 15l-5-5 5-5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
6
|
+
var NEXT_ICON = `<svg class="nav-icon" viewBox="0 0 20 20" fill="none"><path d="M7.5 5l5 5-5 5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
|
|
7
|
+
var BvPagination = class extends HTMLElement {
|
|
8
|
+
static observedAttributes = ["page", "total-pages", "total", "page-size", "siblings"];
|
|
9
|
+
_rendered = false;
|
|
10
|
+
_pagesEl = null;
|
|
11
|
+
_prevBtn = null;
|
|
12
|
+
_nextBtn = null;
|
|
13
|
+
_rangeEl = null;
|
|
14
|
+
constructor() {
|
|
15
|
+
super();
|
|
16
|
+
this.attachShadow({ mode: "open" });
|
|
17
|
+
if ("replaceSync" in CSSStyleSheet.prototype) {
|
|
18
|
+
const sheet = new CSSStyleSheet();
|
|
19
|
+
sheet.replaceSync(bv_pagination_default);
|
|
20
|
+
this.shadowRoot.adoptedStyleSheets = [sheet];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
connectedCallback() {
|
|
24
|
+
this._render();
|
|
25
|
+
}
|
|
26
|
+
attributeChangedCallback() {
|
|
27
|
+
if (this._rendered) this._update();
|
|
28
|
+
}
|
|
29
|
+
get page() {
|
|
30
|
+
return parseInt(this.getAttribute("page") ?? "1", 10);
|
|
31
|
+
}
|
|
32
|
+
get totalPages() {
|
|
33
|
+
return parseInt(this.getAttribute("total-pages") ?? "1", 10);
|
|
34
|
+
}
|
|
35
|
+
get total() {
|
|
36
|
+
return parseInt(this.getAttribute("total") ?? "0", 10);
|
|
37
|
+
}
|
|
38
|
+
get pageSize() {
|
|
39
|
+
return parseInt(this.getAttribute("page-size") ?? "20", 10);
|
|
40
|
+
}
|
|
41
|
+
get siblings() {
|
|
42
|
+
return parseInt(this.getAttribute("siblings") ?? "1", 10);
|
|
43
|
+
}
|
|
44
|
+
_go(p) {
|
|
45
|
+
const { page, totalPages } = this;
|
|
46
|
+
if (p < 1 || p > totalPages || p === page) return;
|
|
47
|
+
this.setAttribute("page", String(p));
|
|
48
|
+
this.dispatchEvent(
|
|
49
|
+
new CustomEvent("bv-page-change", {
|
|
50
|
+
bubbles: true,
|
|
51
|
+
composed: true,
|
|
52
|
+
detail: { page: p }
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
_render() {
|
|
57
|
+
if (this._rendered) return;
|
|
58
|
+
this._rendered = true;
|
|
59
|
+
const shadow = this.shadowRoot;
|
|
60
|
+
if (!shadow.adoptedStyleSheets.length) {
|
|
61
|
+
const s = document.createElement("style");
|
|
62
|
+
s.textContent = bv_pagination_default;
|
|
63
|
+
shadow.appendChild(s);
|
|
64
|
+
}
|
|
65
|
+
const wrap = document.createElement("div");
|
|
66
|
+
wrap.className = "wrap";
|
|
67
|
+
const prevBtn = document.createElement("button");
|
|
68
|
+
prevBtn.className = "btn nav-btn";
|
|
69
|
+
prevBtn.setAttribute("aria-label", "Previous");
|
|
70
|
+
prevBtn.innerHTML = `${PREV_ICON}<span class="nav-label">Previous</span>`;
|
|
71
|
+
prevBtn.addEventListener("click", () => this._go(this.page - 1));
|
|
72
|
+
this._prevBtn = prevBtn;
|
|
73
|
+
const pagesEl = document.createElement("div");
|
|
74
|
+
pagesEl.className = "pages";
|
|
75
|
+
this._pagesEl = pagesEl;
|
|
76
|
+
const rightSection = document.createElement("div");
|
|
77
|
+
rightSection.className = "right-section";
|
|
78
|
+
const rangeEl = document.createElement("span");
|
|
79
|
+
rangeEl.className = "range-label";
|
|
80
|
+
this._rangeEl = rangeEl;
|
|
81
|
+
const nextBtn = document.createElement("button");
|
|
82
|
+
nextBtn.className = "btn nav-btn";
|
|
83
|
+
nextBtn.setAttribute("aria-label", "Next");
|
|
84
|
+
nextBtn.innerHTML = `<span class="nav-label">Next</span>${NEXT_ICON}`;
|
|
85
|
+
nextBtn.addEventListener("click", () => this._go(this.page + 1));
|
|
86
|
+
this._nextBtn = nextBtn;
|
|
87
|
+
rightSection.append(rangeEl, nextBtn);
|
|
88
|
+
wrap.append(prevBtn, pagesEl, rightSection);
|
|
89
|
+
shadow.appendChild(wrap);
|
|
90
|
+
this._update();
|
|
91
|
+
}
|
|
92
|
+
_update() {
|
|
93
|
+
const { page, totalPages, total, pageSize, siblings } = this;
|
|
94
|
+
if (this._prevBtn) this._prevBtn.disabled = page <= 1;
|
|
95
|
+
if (this._nextBtn) this._nextBtn.disabled = page >= totalPages;
|
|
96
|
+
if (this._rangeEl) {
|
|
97
|
+
if (total > 0) {
|
|
98
|
+
const start = (page - 1) * pageSize + 1;
|
|
99
|
+
const end = Math.min(page * pageSize, total);
|
|
100
|
+
this._rangeEl.textContent = `${start} - ${end} of ${total}`;
|
|
101
|
+
this._rangeEl.hidden = false;
|
|
102
|
+
} else {
|
|
103
|
+
this._rangeEl.hidden = true;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (!this._pagesEl) return;
|
|
107
|
+
this._pagesEl.innerHTML = "";
|
|
108
|
+
const pages = this._pageRange(page, totalPages, siblings);
|
|
109
|
+
let lastPage = 0;
|
|
110
|
+
for (const p of pages) {
|
|
111
|
+
if (p - lastPage > 1) {
|
|
112
|
+
const el = document.createElement("span");
|
|
113
|
+
el.className = "ellipsis";
|
|
114
|
+
el.textContent = "\u2026";
|
|
115
|
+
this._pagesEl.appendChild(el);
|
|
116
|
+
}
|
|
117
|
+
const btn = document.createElement("button");
|
|
118
|
+
btn.className = "btn page-btn" + (p === page ? " active" : "");
|
|
119
|
+
btn.textContent = String(p);
|
|
120
|
+
btn.addEventListener("click", () => this._go(p));
|
|
121
|
+
this._pagesEl.appendChild(btn);
|
|
122
|
+
lastPage = p;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
_pageRange(current, total, siblings) {
|
|
126
|
+
const left = Math.max(2, current - siblings);
|
|
127
|
+
const right = Math.min(total - 1, current + siblings);
|
|
128
|
+
const pages = [1];
|
|
129
|
+
for (let i = left; i <= right; i++) pages.push(i);
|
|
130
|
+
if (total > 1) pages.push(total);
|
|
131
|
+
return [...new Set(pages)].sort((a, b) => a - b);
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
if (!customElements.get("bv-pagination")) {
|
|
135
|
+
customElements.define("bv-pagination", BvPagination);
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
BvPagination
|
|
139
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import '../bv-user-row/bv-user-row.ts';
|
|
2
|
+
import '../bv-promo-banner/bv-promo-banner.ts';
|
|
3
|
+
import '../bv-searchbox/bv-searchbox.ts';
|
|
4
|
+
export declare class BvPortalHeader extends HTMLElement {
|
|
5
|
+
static readonly observedAttributes: string[];
|
|
6
|
+
private _rendered;
|
|
7
|
+
private _els;
|
|
8
|
+
constructor();
|
|
9
|
+
connectedCallback(): void;
|
|
10
|
+
attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
|
|
11
|
+
private _render;
|
|
12
|
+
}
|