@bluevolt-tech/lumen 2.0.0 → 2.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/README.md +37 -23
- package/dist/components/_shared/adopt-styles.d.ts +8 -0
- package/dist/components/_shared/date-range-validator.d.ts +61 -0
- package/dist/components/_shared/dropdown-controller.d.ts +31 -0
- package/dist/components/_shared/selectable-card.d.ts +10 -0
- package/dist/components/bv-alert-banner/bv-alert-banner.js +19 -17
- package/dist/components/bv-avatar/bv-avatar.js +19 -11
- package/dist/components/bv-badge/bv-badge.js +19 -11
- package/dist/components/bv-button/bv-button.js +18 -16
- package/dist/components/bv-category-pill/bv-category-pill.js +18 -16
- package/dist/components/bv-checkbox/bv-checkbox.js +19 -11
- package/dist/components/bv-chip/bv-chip.js +19 -11
- package/dist/components/bv-course-detail/bv-course-detail.js +20 -34
- package/dist/components/bv-course-detail-modal/bv-course-detail-modal.js +24 -90
- package/dist/components/bv-course-grid-card/bv-course-grid-card.d.ts +2 -2
- package/dist/components/bv-course-grid-card/bv-course-grid-card.js +105 -55
- package/dist/components/bv-course-list-card/bv-course-list-card.d.ts +2 -2
- package/dist/components/bv-course-list-card/bv-course-list-card.js +105 -55
- package/dist/components/bv-course-outline/bv-course-outline.js +19 -11
- package/dist/components/bv-date-range-input/bv-date-range-input.d.ts +4 -6
- package/dist/components/bv-date-range-input/bv-date-range-input.js +460 -122
- package/dist/components/bv-date-range-picker/bv-date-range-picker.d.ts +17 -3
- package/dist/components/bv-date-range-picker/bv-date-range-picker.js +339 -73
- package/dist/components/bv-empty-state/bv-empty-state.js +20 -28
- package/dist/components/bv-filter-dropdown/bv-filter-dropdown.d.ts +1 -4
- package/dist/components/bv-filter-dropdown/bv-filter-dropdown.js +78 -53
- package/dist/components/bv-filter-panel/bv-filter-panel.js +20 -22
- package/dist/components/bv-icon/bv-icon.js +19 -11
- package/dist/components/bv-input/bv-input.js +18 -16
- package/dist/components/bv-input-dropdown/bv-input-dropdown.d.ts +1 -4
- package/dist/components/bv-input-dropdown/bv-input-dropdown.js +77 -78
- package/dist/components/bv-modal/bv-modal.js +19 -11
- package/dist/components/bv-page-title/bv-page-title.js +19 -6
- package/dist/components/bv-pagination/bv-pagination.d.ts +1 -0
- package/dist/components/bv-pagination/bv-pagination.js +23 -186
- package/dist/components/bv-portal-header/bv-portal-header.js +25 -83
- package/dist/components/bv-portal-layout/bv-portal-layout.js +19 -11
- package/dist/components/bv-progress-bar/bv-progress-bar.js +19 -11
- package/dist/components/bv-promo-banner/bv-promo-banner.js +19 -11
- package/dist/components/bv-radio/bv-radio.js +19 -11
- package/dist/components/bv-searchbox/bv-searchbox.js +19 -11
- package/dist/components/bv-segmented-control/bv-segmented-control.js +18 -16
- package/dist/components/bv-select/bv-select.d.ts +1 -4
- package/dist/components/bv-select/bv-select.js +76 -44
- package/dist/components/bv-split-button/bv-split-button.d.ts +1 -4
- package/dist/components/bv-split-button/bv-split-button.js +76 -42
- package/dist/components/bv-star-rating/bv-star-rating.js +19 -11
- package/dist/components/bv-table/bv-table.d.ts +5 -0
- package/dist/components/bv-table/bv-table.js +69 -19
- package/dist/components/bv-toggle/bv-toggle.js +19 -11
- package/dist/components/bv-tooltip/bv-tooltip.js +19 -17
- package/dist/components/bv-user-row/bv-user-row.js +22 -50
- package/dist/components/bv-view-switcher/bv-view-switcher.js +19 -11
- package/dist/themes/base.css +2 -1
- package/package.json +8 -1
- package/themes/base.css +2 -1
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-course-detail/bv-course-detail.css
|
|
2
2
|
var bv_course_detail_default = ":host {\n display: block;\n font-family: var(--bv-font-family-base);\n}\n\n[hidden] {\n display: none !important;\n}\n\n/* \u2500\u2500 Root layout \u2500\u2500 */\n\n.course-detail {\n display: flex;\n gap: 20px;\n align-items: flex-start;\n}\n\n/* \u2500\u2500 Thumbnail column \u2500\u2500 */\n\n.thumb-col {\n flex-shrink: 0;\n width: 160px;\n}\n\n.thumb-wrap {\n width: 160px;\n height: 113px;\n background: var(--bv-color-neutral-200);\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.thumb-img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.thumb-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n}\n\n.thumb-placeholder svg {\n width: 100%;\n height: 100%;\n}\n\n/* \u2500\u2500 Right column \u2500\u2500 */\n\n.right-col {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n/* \u2500\u2500 Top row: pills + title + separator \u2500\u2500 */\n\n.top-row {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.card-header {\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n\n.pills-row {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n}\n\n.course-title {\n font-size: var(--bv-font-size-xl);\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n line-height: 32px;\n}\n\n.separator {\n height: 0;\n border-top: 0.5px solid var(--bv-color-neutral-300);\n}\n\n/* \u2500\u2500 Description \u2500\u2500 */\n\n.desc-section {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n\n.desc-text {\n margin: 0;\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 20px;\n display: -webkit-box;\n -webkit-line-clamp: 6;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n\n/* Read More expands the clamp */\n.desc-wrap--expanded .desc-text {\n -webkit-line-clamp: unset;\n}\n\n.read-more-btn {\n background: none;\n border: none;\n padding: 0;\n cursor: pointer;\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-primary);\n line-height: 24px;\n white-space: nowrap;\n text-align: left;\n}\n\n.read-more-btn:hover {\n text-decoration: underline;\n}\n";
|
|
3
3
|
|
|
4
|
+
// components/_shared/adopt-styles.ts
|
|
5
|
+
var _sheetCache = /* @__PURE__ */ new Map();
|
|
6
|
+
function adoptStyles(shadow, css) {
|
|
7
|
+
if ("adoptedStyleSheets" in ShadowRoot.prototype && typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
|
|
8
|
+
let sheet = _sheetCache.get(css);
|
|
9
|
+
if (!sheet) {
|
|
10
|
+
sheet = new CSSStyleSheet();
|
|
11
|
+
sheet.replaceSync(css);
|
|
12
|
+
_sheetCache.set(css, sheet);
|
|
13
|
+
}
|
|
14
|
+
shadow.adoptedStyleSheets = [sheet];
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const style = document.createElement("style");
|
|
18
|
+
style.textContent = css;
|
|
19
|
+
shadow.appendChild(style);
|
|
20
|
+
}
|
|
21
|
+
|
|
4
22
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-category-pill/bv-category-pill.css
|
|
5
23
|
var bv_category_pill_default = ":host {\n display: inline-flex;\n font-family: var(--bv-font-family-base);\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 6px;\n border: 0.5px solid var(--bv-color-neutral-900);\n border-radius: var(--bv-radius-sm);\n font-size: 10px;\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 1;\n white-space: nowrap;\n}\n";
|
|
6
24
|
|
|
7
25
|
// components/bv-category-pill/bv-category-pill.ts
|
|
8
|
-
var _sheet = null;
|
|
9
|
-
function getSheet() {
|
|
10
|
-
if (!_sheet) {
|
|
11
|
-
_sheet = new CSSStyleSheet();
|
|
12
|
-
_sheet.replaceSync(bv_category_pill_default);
|
|
13
|
-
}
|
|
14
|
-
return _sheet;
|
|
15
|
-
}
|
|
16
26
|
var BvCategoryPill = class extends HTMLElement {
|
|
17
27
|
static observedAttributes = ["label"];
|
|
18
28
|
_rendered = false;
|
|
19
29
|
_labelEl = null;
|
|
20
30
|
constructor() {
|
|
21
31
|
super();
|
|
22
|
-
|
|
23
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
24
|
-
shadow.adoptedStyleSheets = [getSheet()];
|
|
25
|
-
}
|
|
32
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_category_pill_default);
|
|
26
33
|
}
|
|
27
34
|
get label() {
|
|
28
35
|
return this.getAttribute("label") ?? "";
|
|
@@ -41,11 +48,6 @@ var BvCategoryPill = class extends HTMLElement {
|
|
|
41
48
|
if (this._rendered) return;
|
|
42
49
|
this._rendered = true;
|
|
43
50
|
const shadow = this.shadowRoot;
|
|
44
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
45
|
-
const s = document.createElement("style");
|
|
46
|
-
s.textContent = bv_category_pill_default;
|
|
47
|
-
shadow.appendChild(s);
|
|
48
|
-
}
|
|
49
51
|
const pill = document.createElement("span");
|
|
50
52
|
pill.className = "pill";
|
|
51
53
|
pill.setAttribute("part", "pill");
|
|
@@ -61,14 +63,6 @@ if (!customElements.get("bv-category-pill")) {
|
|
|
61
63
|
}
|
|
62
64
|
|
|
63
65
|
// components/bv-course-detail/bv-course-detail.ts
|
|
64
|
-
var _sheet2 = null;
|
|
65
|
-
function getSheet2() {
|
|
66
|
-
if (!_sheet2) {
|
|
67
|
-
_sheet2 = new CSSStyleSheet();
|
|
68
|
-
_sheet2.replaceSync(bv_course_detail_default);
|
|
69
|
-
}
|
|
70
|
-
return _sheet2;
|
|
71
|
-
}
|
|
72
66
|
var BvCourseDetail = class extends HTMLElement {
|
|
73
67
|
static observedAttributes = ["thumbnail", "title", "description", "categories"];
|
|
74
68
|
_rendered = false;
|
|
@@ -82,10 +76,7 @@ var BvCourseDetail = class extends HTMLElement {
|
|
|
82
76
|
_readMoreBtn = null;
|
|
83
77
|
constructor() {
|
|
84
78
|
super();
|
|
85
|
-
|
|
86
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
87
|
-
shadow.adoptedStyleSheets = [getSheet2()];
|
|
88
|
-
}
|
|
79
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_course_detail_default);
|
|
89
80
|
}
|
|
90
81
|
get thumbnail() {
|
|
91
82
|
return this.getAttribute("thumbnail") ?? "";
|
|
@@ -150,11 +141,6 @@ var BvCourseDetail = class extends HTMLElement {
|
|
|
150
141
|
}
|
|
151
142
|
}
|
|
152
143
|
const shadow = this.shadowRoot;
|
|
153
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
154
|
-
const s = document.createElement("style");
|
|
155
|
-
s.textContent = bv_course_detail_default;
|
|
156
|
-
shadow.appendChild(s);
|
|
157
|
-
}
|
|
158
144
|
const root = document.createElement("div");
|
|
159
145
|
root.className = "course-detail";
|
|
160
146
|
const thumbCol = document.createElement("div");
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-course-detail-modal/bv-course-detail-modal.css
|
|
2
2
|
var bv_course_detail_modal_default = ":host {\n display: contents;\n font-family: var(--bv-font-family-base);\n}\n\n/* Ensure hidden attribute works on slotted custom elements */\n[hidden] {\n display: none !important;\n}\n\n.modal-body {\n display: flex;\n flex-direction: column;\n gap: 20px;\n width: 100%;\n}\n";
|
|
3
3
|
|
|
4
|
+
// components/_shared/adopt-styles.ts
|
|
5
|
+
var _sheetCache = /* @__PURE__ */ new Map();
|
|
6
|
+
function adoptStyles(shadow, css) {
|
|
7
|
+
if ("adoptedStyleSheets" in ShadowRoot.prototype && typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
|
|
8
|
+
let sheet = _sheetCache.get(css);
|
|
9
|
+
if (!sheet) {
|
|
10
|
+
sheet = new CSSStyleSheet();
|
|
11
|
+
sheet.replaceSync(css);
|
|
12
|
+
_sheetCache.set(css, sheet);
|
|
13
|
+
}
|
|
14
|
+
shadow.adoptedStyleSheets = [sheet];
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const style = document.createElement("style");
|
|
18
|
+
style.textContent = css;
|
|
19
|
+
shadow.appendChild(style);
|
|
20
|
+
}
|
|
21
|
+
|
|
4
22
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-modal/bv-modal.css
|
|
5
23
|
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';
|
|
6
24
|
|
|
@@ -12,12 +30,7 @@ var BvModal = class extends HTMLElement {
|
|
|
12
30
|
_rendered = false;
|
|
13
31
|
constructor() {
|
|
14
32
|
super();
|
|
15
|
-
this.attachShadow({ mode: "open" });
|
|
16
|
-
if (typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
|
|
17
|
-
const sheet = new CSSStyleSheet();
|
|
18
|
-
sheet.replaceSync(bv_modal_default);
|
|
19
|
-
this.shadowRoot.adoptedStyleSheets = [sheet];
|
|
20
|
-
}
|
|
33
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_modal_default);
|
|
21
34
|
}
|
|
22
35
|
connectedCallback() {
|
|
23
36
|
this._render();
|
|
@@ -51,11 +64,6 @@ var BvModal = class extends HTMLElement {
|
|
|
51
64
|
if (this._rendered) return;
|
|
52
65
|
this._rendered = true;
|
|
53
66
|
const shadow = this.shadowRoot;
|
|
54
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
55
|
-
const style = document.createElement("style");
|
|
56
|
-
style.textContent = bv_modal_default;
|
|
57
|
-
shadow.appendChild(style);
|
|
58
|
-
}
|
|
59
67
|
const dialog = document.createElement("dialog");
|
|
60
68
|
this._dialog = dialog;
|
|
61
69
|
dialog.addEventListener("click", (e) => {
|
|
@@ -110,24 +118,13 @@ var bv_course_detail_default = ":host {\n display: block;\n font-family: var(-
|
|
|
110
118
|
var bv_category_pill_default = ":host {\n display: inline-flex;\n font-family: var(--bv-font-family-base);\n}\n\n.pill {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px 6px;\n border: 0.5px solid var(--bv-color-neutral-900);\n border-radius: var(--bv-radius-sm);\n font-size: 10px;\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 1;\n white-space: nowrap;\n}\n";
|
|
111
119
|
|
|
112
120
|
// components/bv-category-pill/bv-category-pill.ts
|
|
113
|
-
var _sheet = null;
|
|
114
|
-
function getSheet() {
|
|
115
|
-
if (!_sheet) {
|
|
116
|
-
_sheet = new CSSStyleSheet();
|
|
117
|
-
_sheet.replaceSync(bv_category_pill_default);
|
|
118
|
-
}
|
|
119
|
-
return _sheet;
|
|
120
|
-
}
|
|
121
121
|
var BvCategoryPill = class extends HTMLElement {
|
|
122
122
|
static observedAttributes = ["label"];
|
|
123
123
|
_rendered = false;
|
|
124
124
|
_labelEl = null;
|
|
125
125
|
constructor() {
|
|
126
126
|
super();
|
|
127
|
-
|
|
128
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
129
|
-
shadow.adoptedStyleSheets = [getSheet()];
|
|
130
|
-
}
|
|
127
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_category_pill_default);
|
|
131
128
|
}
|
|
132
129
|
get label() {
|
|
133
130
|
return this.getAttribute("label") ?? "";
|
|
@@ -146,11 +143,6 @@ var BvCategoryPill = class extends HTMLElement {
|
|
|
146
143
|
if (this._rendered) return;
|
|
147
144
|
this._rendered = true;
|
|
148
145
|
const shadow = this.shadowRoot;
|
|
149
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
150
|
-
const s = document.createElement("style");
|
|
151
|
-
s.textContent = bv_category_pill_default;
|
|
152
|
-
shadow.appendChild(s);
|
|
153
|
-
}
|
|
154
146
|
const pill = document.createElement("span");
|
|
155
147
|
pill.className = "pill";
|
|
156
148
|
pill.setAttribute("part", "pill");
|
|
@@ -166,14 +158,6 @@ if (!customElements.get("bv-category-pill")) {
|
|
|
166
158
|
}
|
|
167
159
|
|
|
168
160
|
// components/bv-course-detail/bv-course-detail.ts
|
|
169
|
-
var _sheet2 = null;
|
|
170
|
-
function getSheet2() {
|
|
171
|
-
if (!_sheet2) {
|
|
172
|
-
_sheet2 = new CSSStyleSheet();
|
|
173
|
-
_sheet2.replaceSync(bv_course_detail_default);
|
|
174
|
-
}
|
|
175
|
-
return _sheet2;
|
|
176
|
-
}
|
|
177
161
|
var BvCourseDetail = class extends HTMLElement {
|
|
178
162
|
static observedAttributes = ["thumbnail", "title", "description", "categories"];
|
|
179
163
|
_rendered = false;
|
|
@@ -187,10 +171,7 @@ var BvCourseDetail = class extends HTMLElement {
|
|
|
187
171
|
_readMoreBtn = null;
|
|
188
172
|
constructor() {
|
|
189
173
|
super();
|
|
190
|
-
|
|
191
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
192
|
-
shadow.adoptedStyleSheets = [getSheet2()];
|
|
193
|
-
}
|
|
174
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_course_detail_default);
|
|
194
175
|
}
|
|
195
176
|
get thumbnail() {
|
|
196
177
|
return this.getAttribute("thumbnail") ?? "";
|
|
@@ -255,11 +236,6 @@ var BvCourseDetail = class extends HTMLElement {
|
|
|
255
236
|
}
|
|
256
237
|
}
|
|
257
238
|
const shadow = this.shadowRoot;
|
|
258
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
259
|
-
const s = document.createElement("style");
|
|
260
|
-
s.textContent = bv_course_detail_default;
|
|
261
|
-
shadow.appendChild(s);
|
|
262
|
-
}
|
|
263
239
|
const root = document.createElement("div");
|
|
264
240
|
root.className = "course-detail";
|
|
265
241
|
const thumbCol = document.createElement("div");
|
|
@@ -398,12 +374,7 @@ var BvCourseOutline = class extends HTMLElement {
|
|
|
398
374
|
}
|
|
399
375
|
constructor() {
|
|
400
376
|
super();
|
|
401
|
-
this.attachShadow({ mode: "open" });
|
|
402
|
-
if ("replaceSync" in CSSStyleSheet.prototype) {
|
|
403
|
-
const sheet = new CSSStyleSheet();
|
|
404
|
-
sheet.replaceSync(bv_course_outline_default);
|
|
405
|
-
this.shadowRoot.adoptedStyleSheets = [sheet];
|
|
406
|
-
}
|
|
377
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_course_outline_default);
|
|
407
378
|
}
|
|
408
379
|
connectedCallback() {
|
|
409
380
|
this._render();
|
|
@@ -426,11 +397,6 @@ var BvCourseOutline = class extends HTMLElement {
|
|
|
426
397
|
if (this._rendered) return;
|
|
427
398
|
this._rendered = true;
|
|
428
399
|
const shadow = this.shadowRoot;
|
|
429
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
430
|
-
const s = document.createElement("style");
|
|
431
|
-
s.textContent = bv_course_outline_default;
|
|
432
|
-
shadow.appendChild(s);
|
|
433
|
-
}
|
|
434
400
|
const attr = this.getAttribute("sections");
|
|
435
401
|
if (attr !== null) {
|
|
436
402
|
try {
|
|
@@ -933,14 +899,6 @@ var rawIcons = {
|
|
|
933
899
|
};
|
|
934
900
|
|
|
935
901
|
// components/bv-button/bv-button.ts
|
|
936
|
-
var _sheet3 = null;
|
|
937
|
-
function getSheet3() {
|
|
938
|
-
if (!_sheet3) {
|
|
939
|
-
_sheet3 = new CSSStyleSheet();
|
|
940
|
-
_sheet3.replaceSync(bv_button_default);
|
|
941
|
-
}
|
|
942
|
-
return _sheet3;
|
|
943
|
-
}
|
|
944
902
|
var BvButton = class extends HTMLElement {
|
|
945
903
|
static observedAttributes = [
|
|
946
904
|
"variant",
|
|
@@ -956,10 +914,7 @@ var BvButton = class extends HTMLElement {
|
|
|
956
914
|
];
|
|
957
915
|
constructor() {
|
|
958
916
|
super();
|
|
959
|
-
|
|
960
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
961
|
-
shadow.adoptedStyleSheets = [getSheet3()];
|
|
962
|
-
}
|
|
917
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_button_default);
|
|
963
918
|
}
|
|
964
919
|
// ── Accessors ────────────────────────────────────────────────
|
|
965
920
|
get variant() {
|
|
@@ -1016,11 +971,6 @@ var BvButton = class extends HTMLElement {
|
|
|
1016
971
|
const shadow = this.shadowRoot;
|
|
1017
972
|
let btn = shadow.querySelector("button");
|
|
1018
973
|
if (!btn) {
|
|
1019
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
1020
|
-
const styleEl = document.createElement("style");
|
|
1021
|
-
styleEl.textContent = bv_button_default;
|
|
1022
|
-
shadow.appendChild(styleEl);
|
|
1023
|
-
}
|
|
1024
974
|
btn = document.createElement("button");
|
|
1025
975
|
btn.setAttribute("part", "button");
|
|
1026
976
|
btn.appendChild(document.createElement("slot"));
|
|
@@ -1075,14 +1025,6 @@ if (!customElements.get("bv-button")) {
|
|
|
1075
1025
|
}
|
|
1076
1026
|
|
|
1077
1027
|
// components/bv-course-detail-modal/bv-course-detail-modal.ts
|
|
1078
|
-
var _sheet4 = null;
|
|
1079
|
-
function getSheet4() {
|
|
1080
|
-
if (!_sheet4) {
|
|
1081
|
-
_sheet4 = new CSSStyleSheet();
|
|
1082
|
-
_sheet4.replaceSync(bv_course_detail_modal_default);
|
|
1083
|
-
}
|
|
1084
|
-
return _sheet4;
|
|
1085
|
-
}
|
|
1086
1028
|
var BvCourseDetailModal = class extends HTMLElement {
|
|
1087
1029
|
static observedAttributes = [
|
|
1088
1030
|
"open",
|
|
@@ -1103,10 +1045,7 @@ var BvCourseDetailModal = class extends HTMLElement {
|
|
|
1103
1045
|
_outlineEl = null;
|
|
1104
1046
|
constructor() {
|
|
1105
1047
|
super();
|
|
1106
|
-
|
|
1107
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
1108
|
-
shadow.adoptedStyleSheets = [getSheet4()];
|
|
1109
|
-
}
|
|
1048
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_course_detail_modal_default);
|
|
1110
1049
|
}
|
|
1111
1050
|
get open() {
|
|
1112
1051
|
return this.hasAttribute("open");
|
|
@@ -1229,11 +1168,6 @@ var BvCourseDetailModal = class extends HTMLElement {
|
|
|
1229
1168
|
}
|
|
1230
1169
|
}
|
|
1231
1170
|
const shadow = this.shadowRoot;
|
|
1232
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
1233
|
-
const s = document.createElement("style");
|
|
1234
|
-
s.textContent = bv_course_detail_modal_default;
|
|
1235
|
-
shadow.appendChild(s);
|
|
1236
|
-
}
|
|
1237
1171
|
const modal = document.createElement("bv-modal");
|
|
1238
1172
|
modal.setAttribute("title", this.title);
|
|
1239
1173
|
if (this.open) modal.setAttribute("open", "");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../bv-button/bv-button.ts';
|
|
2
|
-
|
|
2
|
+
import { type SelectableHost } from '../_shared/selectable-card.ts';
|
|
3
|
+
export declare class BvCourseGridCard extends HTMLElement implements SelectableHost {
|
|
3
4
|
static readonly observedAttributes: string[];
|
|
4
5
|
get selected(): boolean;
|
|
5
6
|
set selected(v: boolean);
|
|
@@ -19,5 +20,4 @@ export declare class BvCourseGridCard extends HTMLElement {
|
|
|
19
20
|
connectedCallback(): void;
|
|
20
21
|
attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
|
|
21
22
|
private _render;
|
|
22
|
-
private _syncLoading;
|
|
23
23
|
}
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-course-grid-card/bv-course-grid-card.css
|
|
2
|
-
var bv_course_grid_card_default = ":host {\n display: block;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n padding: 12px;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-xl);\n box-shadow: var(--bv-shadow-sm);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([selected]) .card {\n background: var(--bv-color-primary-50);\n border-color: var(--bv-color-primary);\n box-shadow: none;\n}\n\n/* Thumbnail */\n.thumbnail-wrap {\n position: relative;\n width: 100%;\n height: 153px;\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n background: var(--bv-color-neutral-200);\n flex-shrink: 0;\n}\n\n.thumbnail {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.status-badge {\n position: absolute;\n top: 6px;\n right: 6px;\n padding: 0 var(--bv-spacing-sm);\n border-radius: var(--bv-radius-sm);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-medium);\n line-height: 18px;\n background: var(--bv-color-success-light);\n color: var(--bv-color-success-dark);\n}\n\n/* Content */\n.content {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n}\n\n.title {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-md);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-900);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.publisher {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-500);\n}\n\n.publisher strong {\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n}\n\n.description {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 20px;\n min-height: 40px; /* Reserve space for 2 lines so cards align at the bottom in the grid, matching the list card's .description-wrap. */\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n margin: 0;\n}\n\n.info-row {\n display: flex;\n gap: var(--bv-spacing-md);\n margin-top: 2px;\n}\n\n.info-item {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-900);\n}\n\n.info-item strong {\n font-weight: var(--bv-font-weight-bold);\n}\n\n/* Actions */\n.actions {\n display: flex;\n gap: var(--bv-spacing-sm);\n align-items: stretch;\n}\n\n.primary-action {\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.secondary-action {\n display: block;\n width: 48px;\n flex-shrink: 0;\n}\n\n/* Disabled selection: card body is no longer interactive */\n:host([disable-selection]) .card {\n cursor: default;\n}\n\n/* Loading skeleton */\n.skeleton {\n display: none;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n flex: 1;\n min-width: 0;\n}\n\n:host([loading]) .card {\n cursor: default;\n}\n\n:host([loading]) .thumbnail-wrap,\n:host([loading]) .content,\n:host([loading]) .actions {\n display: none;\n}\n\n:host([loading]) .skeleton {\n display: flex;\n}\n\n.skeleton-thumb {\n width: 100%;\n height: 153px;\n border-radius: var(--bv-radius-lg);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-line {\n height: 12px;\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-title-line {\n height: 20px;\n width: 70%;\n}\n\n.skeleton-short-line {\n width: 45%;\n}\n\n.skeleton-actions {\n display: flex;\n gap: var(--bv-spacing-sm);\n align-items: stretch;\n margin-top: 2px;\n}\n\n.skeleton-button {\n height: 44px;\n border-radius: var(--bv-radius-md);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-primary {\n flex: 1;\n min-width: 0;\n}\n\n.skeleton-icon-btn {\n width: 48px;\n flex-shrink: 0;\n}\n\n@keyframes bv-skeleton-shimmer {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n";
|
|
2
|
+
var bv_course_grid_card_default = ":host {\n display: block;\n}\n\n.card {\n display: flex;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n padding: 12px;\n background: var(--bv-color-neutral-0);\n border: 1px solid var(--bv-color-neutral-300);\n border-radius: var(--bv-radius-xl);\n box-shadow: var(--bv-shadow-sm);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast);\n}\n\n:host([selected]) .card {\n background: var(--bv-color-primary-50);\n border-color: var(--bv-color-primary);\n box-shadow: none;\n}\n\n.card:focus-visible {\n outline: var(--bv-focus-ring);\n outline-offset: 2px;\n}\n\n/* Thumbnail */\n.thumbnail-wrap {\n position: relative;\n width: 100%;\n height: 153px;\n border-radius: var(--bv-radius-lg);\n overflow: hidden;\n background: var(--bv-color-neutral-200);\n flex-shrink: 0;\n}\n\n.thumbnail {\n width: 100%;\n height: 100%;\n object-fit: cover;\n display: block;\n}\n\n.status-badge {\n position: absolute;\n top: 6px;\n right: 6px;\n padding: 0 var(--bv-spacing-sm);\n border-radius: var(--bv-radius-sm);\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-medium);\n line-height: 18px;\n background: var(--bv-color-success-light);\n color: var(--bv-color-success-dark);\n}\n\n/* Content */\n.content {\n display: flex;\n flex-direction: column;\n gap: 4px;\n flex: 1;\n min-width: 0;\n}\n\n.title {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-md);\n font-weight: var(--bv-font-weight-semibold);\n color: var(--bv-color-neutral-900);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.publisher {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-xs);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-500);\n}\n\n.publisher strong {\n font-weight: var(--bv-font-weight-medium);\n color: var(--bv-color-neutral-900);\n}\n\n.description {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-700);\n line-height: 20px;\n min-height: 40px; /* Reserve space for 2 lines so cards align at the bottom in the grid, matching the list card's .description-wrap. */\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n margin: 0;\n}\n\n.info-row {\n display: flex;\n gap: var(--bv-spacing-md);\n margin-top: 2px;\n}\n\n.info-item {\n font-family: var(--bv-font-family-base);\n font-size: var(--bv-font-size-sm);\n font-weight: var(--bv-font-weight-regular);\n color: var(--bv-color-neutral-900);\n}\n\n.info-item strong {\n font-weight: var(--bv-font-weight-bold);\n}\n\n/* Actions */\n.actions {\n display: flex;\n gap: var(--bv-spacing-sm);\n align-items: stretch;\n}\n\n.primary-action {\n display: block;\n flex: 1;\n min-width: 0;\n}\n\n.secondary-action {\n display: block;\n width: 48px;\n flex-shrink: 0;\n}\n\n/* Disabled selection: card body is no longer interactive */\n:host([disable-selection]) .card {\n cursor: default;\n}\n\n/* Loading skeleton */\n.skeleton {\n display: none;\n flex-direction: column;\n gap: var(--bv-spacing-sm);\n flex: 1;\n min-width: 0;\n}\n\n:host([loading]) .card {\n cursor: default;\n}\n\n:host([loading]) .thumbnail-wrap,\n:host([loading]) .content,\n:host([loading]) .actions {\n display: none;\n}\n\n:host([loading]) .skeleton {\n display: flex;\n}\n\n.skeleton-thumb {\n width: 100%;\n height: 153px;\n border-radius: var(--bv-radius-lg);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-line {\n height: 12px;\n border-radius: var(--bv-radius-sm);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-title-line {\n height: 20px;\n width: 70%;\n}\n\n.skeleton-short-line {\n width: 45%;\n}\n\n.skeleton-actions {\n display: flex;\n gap: var(--bv-spacing-sm);\n align-items: stretch;\n margin-top: 2px;\n}\n\n.skeleton-button {\n height: 44px;\n border-radius: var(--bv-radius-md);\n background: var(--bv-color-neutral-200);\n animation: bv-skeleton-shimmer 1.5s ease-in-out infinite;\n}\n\n.skeleton-primary {\n flex: 1;\n min-width: 0;\n}\n\n.skeleton-icon-btn {\n width: 48px;\n flex-shrink: 0;\n}\n\n@keyframes bv-skeleton-shimmer {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n";
|
|
3
|
+
|
|
4
|
+
// components/_shared/adopt-styles.ts
|
|
5
|
+
var _sheetCache = /* @__PURE__ */ new Map();
|
|
6
|
+
function adoptStyles(shadow, css) {
|
|
7
|
+
if ("adoptedStyleSheets" in ShadowRoot.prototype && typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype) {
|
|
8
|
+
let sheet = _sheetCache.get(css);
|
|
9
|
+
if (!sheet) {
|
|
10
|
+
sheet = new CSSStyleSheet();
|
|
11
|
+
sheet.replaceSync(css);
|
|
12
|
+
_sheetCache.set(css, sheet);
|
|
13
|
+
}
|
|
14
|
+
shadow.adoptedStyleSheets = [sheet];
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const style = document.createElement("style");
|
|
18
|
+
style.textContent = css;
|
|
19
|
+
shadow.appendChild(style);
|
|
20
|
+
}
|
|
3
21
|
|
|
4
22
|
// css-inline:/home/runner/work/BV_lumen/BV_lumen/components/bv-button/bv-button.css
|
|
5
23
|
var bv_button_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 these three properties per-instance:\n\n HTML: <bv-button style=\"--bv-button-bg: #e53e3e;\">\n Angular: <bv-button [style.--bv-button-bg]=\"brandColor\">\n JavaScript: btn.style.setProperty('--bv-button-bg', value)\n\n Hover is auto-computed from the base colors via color-mix().\n Override --bv-button-bg-hover / --bv-button-border-color-hover\n if you need explicit control over the hovered state.\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 /* Default values \u2014 map to global tokens (primary variant) */\n --bv-button-bg: var(--bv-color-primary);\n --bv-button-bg-hover: color-mix(in srgb, var(--bv-button-bg) 82%, black);\n --bv-button-color: var(--bv-color-neutral-0);\n --bv-button-border-color: var(--bv-color-primary);\n --bv-button-border-color-hover: color-mix(in srgb, var(--bv-button-border-color) 82%, black);\n --bv-button-font-family: var(--bv-font-family-base);\n --bv-button-font-size: var(--bv-font-size-sm);\n\n display: inline-block;\n font-family: var(--bv-font-family-base);\n}\n\n:host([hidden]) {\n /* `!important` so `hidden` always wins over :host([full-width]) / other display rules. */\n display: none !important;\n}\n\n:host([full-width]) {\n display: block;\n width: 100%;\n}\n\n/* \u2500\u2500 Variant tokens \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 Each variant re-points the component tokens to different global\n tokens. Apps can still override with inline styles \u2014 inline style\n always wins due to higher specificity.\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\n:host([variant='secondary']) {\n --bv-button-bg: var(--bv-color-secondary);\n --bv-button-border-color: var(--bv-color-secondary);\n --bv-button-color: var(--bv-color-secondary-foreground);\n}\n\n:host([variant='tertiary']) {\n --bv-button-bg: var(--bv-color-tertiary);\n --bv-button-border-color: var(--bv-color-tertiary);\n}\n\n:host([variant='danger']) {\n --bv-button-bg: var(--bv-color-danger);\n --bv-button-border-color: var(--bv-color-danger);\n}\n\n:host([variant='ghost']) {\n --bv-button-bg: transparent;\n --bv-button-bg-hover: var(--bv-color-primary-light);\n --bv-button-color: var(--bv-color-primary);\n --bv-button-border-color: transparent;\n --bv-button-border-color-hover: transparent;\n}\n\n:host([variant='outline']) {\n --bv-button-bg: transparent;\n --bv-button-bg-hover: var(--bv-color-primary-light);\n --bv-button-color: var(--bv-color-primary);\n --bv-button-border-color: var(--bv-color-primary);\n --bv-button-border-color-hover: var(--bv-color-primary);\n}\n\n:host([variant='outline-secondary']) {\n --bv-button-bg: transparent;\n --bv-button-bg-hover: var(--bv-color-neutral-100);\n --bv-button-color: var(--bv-color-neutral-700);\n --bv-button-border-color: var(--bv-color-neutral-300);\n --bv-button-border-color-hover: var(--bv-color-neutral-300);\n}\n\n/* \u2500\u2500 Base button \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 All visual properties read from the component-level tokens above.\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\n.btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--bv-spacing-xs);\n padding: 10px var(--bv-spacing-md);\n min-height: 40px;\n width: auto;\n font-family: var(--bv-button-font-family);\n font-size: var(--bv-button-font-size);\n font-style: normal;\n font-weight: var(--bv-font-weight-semibold);\n line-height: 20px;\n border: 1px solid var(--bv-button-border-color);\n border-radius: var(--bv-radius-lg);\n cursor: pointer;\n transition:\n background var(--bv-transition-fast),\n color var(--bv-transition-fast),\n border-color var(--bv-transition-fast),\n box-shadow var(--bv-transition-fast),\n opacity var(--bv-transition-fast);\n white-space: nowrap;\n user-select: none;\n text-decoration: none;\n outline: none;\n box-sizing: border-box;\n background: var(--bv-button-bg);\n color: var(--bv-button-color);\n box-shadow: var(--bv-shadow-sm);\n}\n\n:host([full-width]) .btn {\n width: 100%;\n}\n\n.btn:hover:not(:disabled) {\n background: var(--bv-button-bg-hover);\n border-color: var(--bv-button-border-color-hover);\n}\n\n.btn:active:not(:disabled) {\n transform: translateY(1px);\n}\n\n.btn:focus-visible {\n outline: 2px solid var(--bv-button-border-color);\n outline-offset: 2px;\n}\n\n.btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n}\n\n/* \u2500\u2500 Sizes \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:host([size='sm']) .btn {\n padding: 6px 12px;\n min-height: 32px;\n font-size: var(--bv-font-size-sm);\n}\n\n:host([size='lg']) .btn {\n padding: 12px var(--bv-spacing-lg);\n min-height: 48px;\n font-size: var(--bv-font-size-md);\n}\n\n/* \u2500\u2500 Icon \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.btn-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n line-height: 0;\n}\n\n/* \u2500\u2500 Count badge \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.btn-count {\n opacity: 0.8;\n font-weight: var(--bv-font-weight-regular);\n}\n\n/* \u2500\u2500 Loading spinner \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.spinner {\n display: inline-block;\n width: 1em;\n height: 1em;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n flex-shrink: 0;\n animation: bv-spin 700ms linear infinite;\n}\n\n@keyframes bv-spin {\n to {\n transform: rotate(360deg);\n }\n}\n";
|
|
@@ -78,14 +96,6 @@ var rawIcons = {
|
|
|
78
96
|
};
|
|
79
97
|
|
|
80
98
|
// components/bv-button/bv-button.ts
|
|
81
|
-
var _sheet = null;
|
|
82
|
-
function getSheet() {
|
|
83
|
-
if (!_sheet) {
|
|
84
|
-
_sheet = new CSSStyleSheet();
|
|
85
|
-
_sheet.replaceSync(bv_button_default);
|
|
86
|
-
}
|
|
87
|
-
return _sheet;
|
|
88
|
-
}
|
|
89
99
|
var BvButton = class extends HTMLElement {
|
|
90
100
|
static observedAttributes = [
|
|
91
101
|
"variant",
|
|
@@ -101,10 +111,7 @@ var BvButton = class extends HTMLElement {
|
|
|
101
111
|
];
|
|
102
112
|
constructor() {
|
|
103
113
|
super();
|
|
104
|
-
|
|
105
|
-
if ("adoptedStyleSheets" in ShadowRoot.prototype) {
|
|
106
|
-
shadow.adoptedStyleSheets = [getSheet()];
|
|
107
|
-
}
|
|
114
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_button_default);
|
|
108
115
|
}
|
|
109
116
|
// ── Accessors ────────────────────────────────────────────────
|
|
110
117
|
get variant() {
|
|
@@ -161,11 +168,6 @@ var BvButton = class extends HTMLElement {
|
|
|
161
168
|
const shadow = this.shadowRoot;
|
|
162
169
|
let btn = shadow.querySelector("button");
|
|
163
170
|
if (!btn) {
|
|
164
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
165
|
-
const styleEl = document.createElement("style");
|
|
166
|
-
styleEl.textContent = bv_button_default;
|
|
167
|
-
shadow.appendChild(styleEl);
|
|
168
|
-
}
|
|
169
171
|
btn = document.createElement("button");
|
|
170
172
|
btn.setAttribute("part", "button");
|
|
171
173
|
btn.appendChild(document.createElement("slot"));
|
|
@@ -219,6 +221,65 @@ if (!customElements.get("bv-button")) {
|
|
|
219
221
|
customElements.define("bv-button", BvButton);
|
|
220
222
|
}
|
|
221
223
|
|
|
224
|
+
// components/_shared/selectable-card.ts
|
|
225
|
+
function buildAriaLabel(host) {
|
|
226
|
+
const title = host.getAttribute("title") ?? "";
|
|
227
|
+
const publisher = host.getAttribute("publisher") ?? "";
|
|
228
|
+
const parts = [];
|
|
229
|
+
if (title) parts.push(title);
|
|
230
|
+
if (publisher) parts.push(`by ${publisher}`);
|
|
231
|
+
return parts.join(", ");
|
|
232
|
+
}
|
|
233
|
+
function setPrefixedStrong(el, prefix, val) {
|
|
234
|
+
if (!el) return;
|
|
235
|
+
const value = val ?? "";
|
|
236
|
+
if (!value) {
|
|
237
|
+
el.hidden = true;
|
|
238
|
+
el.replaceChildren();
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
el.hidden = false;
|
|
242
|
+
const strong = document.createElement("strong");
|
|
243
|
+
strong.textContent = value;
|
|
244
|
+
if (prefix) el.replaceChildren(document.createTextNode(prefix), strong);
|
|
245
|
+
else el.replaceChildren(strong);
|
|
246
|
+
}
|
|
247
|
+
function syncSelectionA11y(host, card) {
|
|
248
|
+
const inert = host.disableSelection || host.loading;
|
|
249
|
+
card.setAttribute("tabindex", inert ? "-1" : "0");
|
|
250
|
+
if (inert) card.setAttribute("aria-disabled", "true");
|
|
251
|
+
else card.removeAttribute("aria-disabled");
|
|
252
|
+
}
|
|
253
|
+
function syncCardLoading(host, card) {
|
|
254
|
+
card.setAttribute("aria-busy", host.loading ? "true" : "false");
|
|
255
|
+
}
|
|
256
|
+
function bindCardSelection(host, card, actions) {
|
|
257
|
+
const toggle = () => {
|
|
258
|
+
host.selected = !host.selected;
|
|
259
|
+
host.dispatchEvent(
|
|
260
|
+
new CustomEvent("bv-select", {
|
|
261
|
+
bubbles: true,
|
|
262
|
+
composed: true,
|
|
263
|
+
detail: { selected: host.selected }
|
|
264
|
+
})
|
|
265
|
+
);
|
|
266
|
+
};
|
|
267
|
+
const isInert = () => host.disableSelection || host.loading;
|
|
268
|
+
const originatesFromActions = (e) => e.composedPath().includes(actions);
|
|
269
|
+
card.addEventListener("click", (e) => {
|
|
270
|
+
if (isInert()) return;
|
|
271
|
+
if (originatesFromActions(e)) return;
|
|
272
|
+
toggle();
|
|
273
|
+
});
|
|
274
|
+
card.addEventListener("keydown", (e) => {
|
|
275
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
276
|
+
if (isInert()) return;
|
|
277
|
+
if (originatesFromActions(e)) return;
|
|
278
|
+
e.preventDefault();
|
|
279
|
+
toggle();
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
222
283
|
// components/bv-course-grid-card/bv-course-grid-card.ts
|
|
223
284
|
var BvCourseGridCard = class extends HTMLElement {
|
|
224
285
|
static observedAttributes = [
|
|
@@ -286,12 +347,7 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
286
347
|
_els = {};
|
|
287
348
|
constructor() {
|
|
288
349
|
super();
|
|
289
|
-
this.attachShadow({ mode: "open" });
|
|
290
|
-
if ("replaceSync" in CSSStyleSheet.prototype) {
|
|
291
|
-
const sheet = new CSSStyleSheet();
|
|
292
|
-
sheet.replaceSync(bv_course_grid_card_default);
|
|
293
|
-
this.shadowRoot.adoptedStyleSheets = [sheet];
|
|
294
|
-
}
|
|
350
|
+
adoptStyles(this.attachShadow({ mode: "open" }), bv_course_grid_card_default);
|
|
295
351
|
}
|
|
296
352
|
connectedCallback() {
|
|
297
353
|
this._render();
|
|
@@ -299,6 +355,7 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
299
355
|
attributeChangedCallback(name, _old, val) {
|
|
300
356
|
var _a;
|
|
301
357
|
if (!this._rendered) return;
|
|
358
|
+
const card = this._els.card;
|
|
302
359
|
const map = {
|
|
303
360
|
thumbnail: () => {
|
|
304
361
|
var _a2;
|
|
@@ -312,19 +369,20 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
312
369
|
},
|
|
313
370
|
title: () => {
|
|
314
371
|
if (this._els.title) this._els.title.textContent = val ?? "";
|
|
372
|
+
card == null ? void 0 : card.setAttribute("aria-label", buildAriaLabel(this));
|
|
315
373
|
},
|
|
316
374
|
publisher: () => {
|
|
317
|
-
|
|
375
|
+
setPrefixedStrong(this._els.publisher, "By ", val);
|
|
376
|
+
card == null ? void 0 : card.setAttribute("aria-label", buildAriaLabel(this));
|
|
318
377
|
},
|
|
319
378
|
description: () => {
|
|
320
379
|
if (this._els.description) this._els.description.textContent = val ?? "";
|
|
321
380
|
},
|
|
322
381
|
duration: () => {
|
|
323
|
-
|
|
382
|
+
setPrefixedStrong(this._els.duration, "", val);
|
|
324
383
|
},
|
|
325
384
|
"last-updated": () => {
|
|
326
|
-
|
|
327
|
-
this._els.lastUpdated.innerHTML = `Last Updated: <strong>${val ?? ""}</strong>`;
|
|
385
|
+
setPrefixedStrong(this._els.lastUpdated, "Last Updated: ", val);
|
|
328
386
|
},
|
|
329
387
|
"primary-label": () => {
|
|
330
388
|
if (this._els.primaryBtn) this._els.primaryBtn.textContent = val ?? "";
|
|
@@ -354,8 +412,17 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
354
412
|
"hide-secondary": () => {
|
|
355
413
|
if (this._els.secondaryBtn) this._els.secondaryBtn.hidden = this.hideSecondary;
|
|
356
414
|
},
|
|
415
|
+
selected: () => {
|
|
416
|
+
card == null ? void 0 : card.setAttribute("aria-checked", this.selected ? "true" : "false");
|
|
417
|
+
},
|
|
418
|
+
"disable-selection": () => {
|
|
419
|
+
if (card) syncSelectionA11y(this, card);
|
|
420
|
+
},
|
|
357
421
|
loading: () => {
|
|
358
|
-
|
|
422
|
+
if (card) {
|
|
423
|
+
syncCardLoading(this, card);
|
|
424
|
+
syncSelectionA11y(this, card);
|
|
425
|
+
}
|
|
359
426
|
}
|
|
360
427
|
};
|
|
361
428
|
(_a = map[name]) == null ? void 0 : _a.call(map);
|
|
@@ -364,13 +431,11 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
364
431
|
if (this._rendered) return;
|
|
365
432
|
this._rendered = true;
|
|
366
433
|
const shadow = this.shadowRoot;
|
|
367
|
-
if (!shadow.adoptedStyleSheets.length) {
|
|
368
|
-
const s = document.createElement("style");
|
|
369
|
-
s.textContent = bv_course_grid_card_default;
|
|
370
|
-
shadow.appendChild(s);
|
|
371
|
-
}
|
|
372
434
|
const card = document.createElement("div");
|
|
373
435
|
card.className = "card";
|
|
436
|
+
card.setAttribute("role", "checkbox");
|
|
437
|
+
card.setAttribute("aria-checked", this.selected ? "true" : "false");
|
|
438
|
+
card.setAttribute("aria-label", buildAriaLabel(this));
|
|
374
439
|
this._els.card = card;
|
|
375
440
|
const thumbWrap = document.createElement("div");
|
|
376
441
|
thumbWrap.className = "thumbnail-wrap";
|
|
@@ -394,8 +459,8 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
394
459
|
this._els.title = title;
|
|
395
460
|
const publisher = document.createElement("span");
|
|
396
461
|
publisher.className = "publisher";
|
|
397
|
-
publisher.innerHTML = `By <strong>${this.getAttribute("publisher") ?? ""}</strong>`;
|
|
398
462
|
this._els.publisher = publisher;
|
|
463
|
+
setPrefixedStrong(publisher, "By ", this.getAttribute("publisher"));
|
|
399
464
|
const description = document.createElement("p");
|
|
400
465
|
description.className = "description";
|
|
401
466
|
description.textContent = this.getAttribute("description") ?? "";
|
|
@@ -404,12 +469,12 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
404
469
|
infoRow.className = "info-row";
|
|
405
470
|
const duration = document.createElement("span");
|
|
406
471
|
duration.className = "info-item";
|
|
407
|
-
duration.innerHTML = `<strong>${this.getAttribute("duration") ?? ""}</strong>`;
|
|
408
472
|
this._els.duration = duration;
|
|
473
|
+
setPrefixedStrong(duration, "", this.getAttribute("duration"));
|
|
409
474
|
const lastUpdated = document.createElement("span");
|
|
410
475
|
lastUpdated.className = "info-item";
|
|
411
|
-
lastUpdated.innerHTML = `Last Updated: <strong>${this.getAttribute("last-updated") ?? ""}</strong>`;
|
|
412
476
|
this._els.lastUpdated = lastUpdated;
|
|
477
|
+
setPrefixedStrong(lastUpdated, "Last Updated: ", this.getAttribute("last-updated"));
|
|
413
478
|
infoRow.append(duration, lastUpdated);
|
|
414
479
|
content.append(title, publisher, description, infoRow);
|
|
415
480
|
const actions = document.createElement("div");
|
|
@@ -448,24 +513,9 @@ var BvCourseGridCard = class extends HTMLElement {
|
|
|
448
513
|
this._els.skeleton = skeleton;
|
|
449
514
|
card.append(thumbWrap, content, actions, skeleton);
|
|
450
515
|
shadow.appendChild(card);
|
|
451
|
-
this
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
if (e.composedPath().includes(this._els.actions)) return;
|
|
455
|
-
this.selected = !this.selected;
|
|
456
|
-
this.dispatchEvent(
|
|
457
|
-
new CustomEvent("bv-select", {
|
|
458
|
-
bubbles: true,
|
|
459
|
-
composed: true,
|
|
460
|
-
detail: { selected: this.selected }
|
|
461
|
-
})
|
|
462
|
-
);
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
_syncLoading() {
|
|
466
|
-
var _a;
|
|
467
|
-
const loading = this.loading;
|
|
468
|
-
(_a = this._els.card) == null ? void 0 : _a.setAttribute("aria-busy", loading ? "true" : "false");
|
|
516
|
+
syncCardLoading(this, card);
|
|
517
|
+
syncSelectionA11y(this, card);
|
|
518
|
+
bindCardSelection(this, card, actions);
|
|
469
519
|
}
|
|
470
520
|
};
|
|
471
521
|
if (!customElements.get("bv-course-grid-card")) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import '../bv-button/bv-button.ts';
|
|
2
|
-
|
|
2
|
+
import { type SelectableHost } from '../_shared/selectable-card.ts';
|
|
3
|
+
export declare class BvCourseListCard extends HTMLElement implements SelectableHost {
|
|
3
4
|
static readonly observedAttributes: string[];
|
|
4
5
|
get selected(): boolean;
|
|
5
6
|
set selected(v: boolean);
|
|
@@ -19,5 +20,4 @@ export declare class BvCourseListCard extends HTMLElement {
|
|
|
19
20
|
connectedCallback(): void;
|
|
20
21
|
attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
|
|
21
22
|
private _render;
|
|
22
|
-
private _syncLoading;
|
|
23
23
|
}
|